![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
Bryan
Joined: 23 Apr 2005 Posts: 73
|
Timer/Button Issue |
Posted: Tue May 17, 2005 2:30 am |
|
|
I have been working with my LCD and A/D and they work together beautifully (you can see what I'm having them do in my code). Unfortunately when I add in a button that is set to do a task when held down for 2 seconds (In this case print "RESET!" on the lcd and toggle a pin) using the Timer1 interrupt, nothing happens. I tested this code (Just the timer1 ISR and button) and it correctly toggles the LED in a separate program without the A/D and LCD active when the button is held down for 2 seconds, so I have a feeling it might have something to do with them. The other puzzling thing is that I tested adding a Timer0 (RTCC) interrupt that toggles an LED each time the ISR is called and it works fine with the LCD and A/D code in there. By the way, my lcd uses control lines A1-A3 and data lines B4-B7. Here is the code:
Code: |
#include <18F1220.h>
#device adc=10
#fuses NOWDT,NOPROTECT,NOLVP,NOMCLR,INTRC_IO
#use delay(clock=8000000)
#include <lcdplant.c>
float ad = 0;
long int count = 0;
#int_timer1
void timer1_isr()
{
if (input(PIN_A7))
{
count++;
}
else
{
count = 0;
}
if (count >= 61)
{
lcd_putc("\fRESET!");
output_toggle(PIN_B1);
count = 0;
}
}
void main()
{
output_a(0x00);
output_b(0x00);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
setup_timer_1(T1_INTERNAL);
setup_adc_ports(sAN0);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
lcd_init();
lcd_putc("A/D: ");
while(true)
{
ad = read_adc();
lcd_gotoxy(6,1);
printf(lcd_putc, "%1.2f", ad);
delay_ms(500);
}
}
|
Anyone see my problem? LCD code below since the LCD setting the tris could also be the problem:
Code: |
////////////////////////////////////////////////////////////////////////////
//// LCDD.C ////
//// Driver for common LCD modules ////
//// ////
//// lcd_init() Must be called before any other function. ////
//// ////
//// lcd_putc(c) Will display c on the next position of the LCD. ////
//// The following have special meaning: ////
//// \f Clear display ////
//// \n Go to start of second line ////
//// \b Move back one position ////
//// ////
//// lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1) ////
//// ////
//// lcd_getc(x,y) Returns character at position x,y on LCD ////
//// ////
////////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,1997 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS C ////
//// compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, reproduction ////
//// or distribution is permitted without written permission. ////
//// Derivative programs created using this software in object code ////
//// form are not restricted in any way. ////
////////////////////////////////////////////////////////////////////////////
// This structure is overlayed onto the data ports so that you may use
// whatever ports you desire
struct lcd_pin_map
{
BOOLEAN dummy; // Pin A0 unused
BOOLEAN enable; // Pin A1
BOOLEAN rw; // Pin A2
BOOLEAN rs; // Pin A3
int unusedA : 4; // Pin A4-A7 unused
int unusedB : 4; // Pin B0-B3 unused
int data : 4; // Pin B4-B7
} lcd;
#if defined(__PCH__)
#locate lcd = 0xF80
#else
#locate lcd = 5
#endif
struct lcd_tris_map
{
BOOLEAN dummy; // PinA0 unused
int control : 3; // Pin A1-A3
int unusedA : 4; // Pin A4-A7 unused
int unusedB : 4; // Pin B0-B3 unused
int data : 4; // Pin B4-B7
} lcdtris;
#if defined(__PCH__)
#locate lcdtris = 0xF92
#else
#locate lcdtris = 0x85
#endif
#define set_tris_lcd(x) lcdtris.data = (x); lcdtris.control = 0;
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the second line
BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
// These bytes need to be sent to the LCD
// to start it up.
// The following are used for setting
// the I/O port direction register.
#define LCD_WRITE 0 // For write mode all pins are out
#define LCD_READ 15 // For read mode data pins are in
BYTE lcd_read_byte() {
BYTE low,high;
set_tris_lcd(LCD_READ);
lcd.rw = 1;
delay_cycles(1);
lcd.enable = 1;
delay_cycles(1);
high = lcd.data;
lcd.enable = 0;
delay_cycles(1);
lcd.enable = 1;
delay_us(1);
low = lcd.data;
lcd.enable = 0;
set_tris_lcd(LCD_WRITE);
return( (high<<4) | low);
}
void lcd_send_nibble( BYTE n ) {
lcd.data = n;
delay_cycles(1);
lcd.enable = 1;
delay_us(2);
lcd.enable = 0;
}
void lcd_send_byte( BYTE address, BYTE n ) {
lcd.rs = 0;
while ( bit_test(lcd_read_byte(),7) ) ;
lcd.rs = address;
delay_cycles(1);
lcd.rw = 0;
delay_cycles(1);
lcd.enable = 0;
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
void lcd_init() {
BYTE i;
set_tris_lcd(LCD_WRITE);
lcd.rs = 0;
lcd.rw = 0;
lcd.enable = 0;
delay_ms(15);
for(i=1;i<=3;++i) {
lcd_send_nibble(3);
delay_ms(5);
}
lcd_send_nibble(2);
for(i=0;i<=3;++i)
lcd_send_byte(0,LCD_INIT_STRING[i]);
}
void lcd_gotoxy( BYTE x, BYTE y) {
BYTE address;
if(y!=1)
address=lcd_line_two;
else
address=0;
address+=x-1;
lcd_send_byte(0,0x80|address);
}
void lcd_putc( char c) {
switch (c) {
case '\f' : lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n' : lcd_gotoxy(1,2); break;
case '\b' : lcd_send_byte(0,0x10); break;
default : lcd_send_byte(1,c); break;
}
}
char lcd_getc( BYTE x, BYTE y) {
char value;
lcd_gotoxy(x,y);
lcd.rs=1;
value = lcd_read_byte();
lcd.rs=0;
return(value);
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
Bryan
Joined: 23 Apr 2005 Posts: 73
|
|
Posted: Tue May 17, 2005 1:46 pm |
|
|
I ran some more tests and determined that it must be the line calling the input into A7 (I also tried other available pins on both ports A and B for this input and none worked) that is the problem. Since I can get an output to toggle using a timer0 ISR successfully, but the button press doesn't work, it seems logical that the problem is not in the interrupt handling but the input detection. What would be disabling or blocking the input of available pins (not used in A/D or LCD operation) when the LCD and A/D are active? |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 17, 2005 1:59 pm |
|
|
You're checking to see if Pin A7 is high. Normally, when you wire
a switch to a micro-controller, you put a pull-up resistor (10K) to Vdd
on the PIC pin. Then you connect that pin to a normally-open switch.
The other side of the switch goes to ground. So when the switch is
pressed, the PIC will read a logic "0" level at the pin.
If this is how you have it wired, then you're looking for the wrong logic
level. You should change it to this:
if (input(PIN_A7) == 0)
For a schematic of this, go to the link below, scroll down to the bottom,
and download the PicDem2 Plus User's Guide. Go to page 19,
which is a schematic. Zoom in on switch S2, which goes to RA4.
Notice the pullup resistor R3. They're using 4.7K. That's OK.
Notice how the switch S2 has two sections ? That's just because
tactile switches are built that way. Also notice the 470 ohm series
resistor R18. That's there as a safety feature. What if pin RA4
is accidently programmed as a output pin, and set to a high level ?
What if you then press the switch ? Without that series resistor,
you would short the high-level output pin to ground, and possibly
destroy the PIC's output driver on that pin.
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010072&part=DM163022 |
|
![](templates/subSilver/images/spacer.gif) |
Bryan
Joined: 23 Apr 2005 Posts: 73
|
|
Posted: Tue May 17, 2005 2:18 pm |
|
|
Thanks for the tip, but I know that my setup works because I have tested it with this code and it works:
Code: |
#include <18F1320.h>
#fuses NOWDT,NOPROTECT,NOLVP,NOMCLR,INTRC_IO// CCPB0
#use delay(clock=8000000)
long count = 0;
#int_rtcc
void timer0_isr()
{
output_toggle(PIN_A0);
}
#int_timer1
void timer1_isr()
{
if (input(PIN_B0))
{
count++;
}
else
{
count = 0;
}
if (count >= 61)
{
output_toggle(PIN_B1);
count = 0;
}
}
void main()
{
SETUP_ADC_PORTS(NO_ANALOGS);
enable_interrupts(INT_RTCC);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_16);
setup_timer_1(T1_INTERNAL);
output_a(0x00);
output_b(0x00);
while(1);
}
|
I wire one end of my button directly to Vdd (no resistor) and the other end (which only activates when the button is closed since the first end is pulled up to Vdd) is connected to ground and the pin I am trying to detect a logic "high" in (In this case, B0). The ground connection is through a 10k resistor and the connection to pin A0 is through a 220 ohm resistor and this setup works beautifully with the code above. It correctly toggles the LED on pin A0 every half second when RTCC overflows and toggles the LED connected to pin B1 whenever the button is held down for 2 seconds (I calculated this by hand so that it would take 2 seconds). When I use this same exact code as shown in the posts above with LCD and A/D, it doesn't work anymore. Only the toggle for the LED that is controlled by the RTCC ISR still works. This is why I am puzzled. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 17, 2005 2:32 pm |
|
|
It's likely that it's not being configured as an input pin or perhaps
as a digital pin. You've got INTRC_IO in your #fuses statement,
so if that's being compiled properly then that shouldn't be the cause.
It's possible that the problem is caused by an interaction with the
LCD driver, since it does set Tris on port A, and you are using port A.
These are things I'd look at. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|