View previous topic :: View next topic |
Author |
Message |
temtronic
Joined: 01 Jul 2010 Posts: 9100 Location: Greensville,Ontario
|
|
Posted: Fri Sep 29, 2017 9:03 am |
|
|
I have to ask, again, why don't you use a known, good KBD driver, the flex_kbd.c version?
It works, can be modifed for any set I/O pins and oh yeah, works.
There's even an ISR based one in the code library, though I've never tried it.
Jay |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
temtronic KDB driver |
Posted: Sat Sep 30, 2017 5:20 pm |
|
|
Temtronic! So where in this library will I change working with the pins RC0, RC1 and RC2 for the columns and RD0, RD1, RD2, RD3 for the lines? For these are the connected pins available for the keyboard on my board.. This is why I could not use this driver.
Code: |
///////////////////////////////////////////////////////////////////////////
//// KBDD.C ////
//// Generic keypad scan driver ////
//// ////
//// kbd_init() Must be called before any other function. ////
//// ////
//// c = kbd_getc(c) Will return a key value if pressed or /0 if not ////
//// This function should be called frequently so as ////
//// not to miss a key press. ////
//// ////
///////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 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. ////
///////////////////////////////////////////////////////////////////////////
////////////////// The following defines the keypad layout on port D
|
+++++++++++++++++++++++++++++
Source file mostly deleted.
Reason: CCS forum rule #10:
10. Don't post the CCS example code or drivers, or ask for such code and drivers
Forum rules:
http://www.ccsinfo.com/forum/viewtopic.php?t=26245
- Forum Moderator
+++++++++++++++++++++++++++++ |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9100 Location: Greensville,Ontario
|
|
Posted: Sat Sep 30, 2017 7:22 pm |
|
|
What you posted (and shouldn't have...CCS forum rule...) is their driver NOT the 'flexible keypad driver'.
\This link...
http://www.ccsinfo.com/forum/viewtopic.php?t=26333
should get you there...
if not, just goto the code library, it's about 7 or 8 entries from the top.
I've been using a $2 3x4 keypad with just 10K pullups attached to an 18F46K22 for about 3 months and no problems.
Someone has posted an ISR driven version, though I've not tested it, too little time, too many outdoor chores to do before Old Man Winter arrives...
Jay |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
variable number did not print on lcd |
Posted: Tue Oct 03, 2017 3:25 pm |
|
|
Hello friends! Could someone explain to me why variable number did not print on lcd? or print and the value does not appear or is reset, making it impossible to be displayed?
Code: |
// Program scans matrix keyboard and flashes LED number of times according to key pressed.
#include <16f877a.h>
#fuses hs, nowdt, nolvp, put, brownout
#use delay (clock=20M)
#use fast_io(a)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
#define LCD_DB4 PIN_A4
#define LCD_DB5 PIN_A3
#define LCD_DB6 PIN_A2
#define LCD_DB7 PIN_A1
#define LCD_RS PIN_E0
#define LCD_E PIN_A5
#include <lcd4bitsMicrostronic.c>
//****Set Keyboard Keyboard Pins.
//#define col0 PIN_C0
#define col0 PIN_E1
#define col1 PIN_C1
#define col2 PIN_C2
#define row0 PIN_D0
#define row1 PIN_D1
#define row2 PIN_D2
#define row3 PIN_D3
//*** Global Variables
#define Led1 PIN_D4
#define Led2 PIN_D5
#define Led3 PIN_D6
char control = 0x01; // Keyboard control variable.!!!!created to scan the columns.
char cont = 0x00; // Interrupt control !!! Timer counter increment variable 0.
int number = 0x00; // Variable stores the keystroke number
//***prototype das funçoes
void pulse(char teclakeypad); // function returns keyboard number and shows on LCD and LED flashes.
//** Interrupt directive of TIMER0.
#int_timer0
void TIMER0(void)
{
// 250*0,2us*256(prescaler)= 13ms
cont++;
if (cont == 17) // 13ms x17= 0,22ms
{
output_toggle(Led1);
if(input(col0) && control == 0x01) // column 1 at high level? control equal to 1?
{
control = 0x02;
output_low(col0);
output_high(col1);
output_high(col2);
if (!input(row0)) pulse(1);
else if (!input(row1)) pulse (4);
else if (!input(row2)) pulse (7);
else if (!input(row3)) pulse (11);
}
else if(input(col1)&& control == 0x02)
{
control = 0x03;
output_high(col0);
output_low (col1);
output_high(col2);
if (!input(row0)) pulse(2);
else if (!input(row1)) pulse (5);
else if (!input(row2)) pulse (8);
else if (!input(row3)) pulse (0);
}
else if(input(col2)&& control == 0x03)
{
control = 0x01;
output_high(col0);
output_high(col1);
output_low(col2);
if (!input(row0)) pulse(3);
else if (!input(row1)) pulse (6);
else if (!input(row2)) pulse (9);
else if (!input(row3)) pulse (12);
} // End Else If
cont=0x00;
}
set_timer0(0);
}
//** Inicio da main
void main(void)
{
set_tris_a(0b00000001);//RA0 as input.
set_tris_c(0x00);
set_tris_d(0x0f);
set_tris_e(0x00);// Port_E as output
output_a(0x00);
output_c(0x07);
output_d(0x0f);
output_E(0x02);
setup_timer_0(rtcc_internal|rtcc_div_256);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
set_timer0(0);
lcd_init();
lcd_putc("\fEnter password:");
while(1) //
{
}// End while(true)
}// End da main
//****** void pulse function, the led flashes the number of times the key is pressed
void pulse (char teclakeypad)
{
char i;
number = teclakeypad;
lcd_gotoxy(1,1);
printf(lcd_putc,"\fnumber entered:");
lcd_gotoxy(7,2);
if (number == 11) lcd_putc("*");
else if(number == 12) lcd_putc("#");
else lcd_putc(number);
for (i=0; i<teclakeypad; i++)
{
output_high(Led3);
delay_ms (400);
output_low(Led3);
delay_ms (400);
}
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9100 Location: Greensville,Ontario
|
|
Posted: Tue Oct 03, 2017 5:11 pm |
|
|
one possibility...
Code: |
lcd_init();
lcd_putc("\fEnter password:");
while(1) //
{
} // End while(true)
|
After you display 'Enter password', your program 'loops forever' and nowhere within the Timer ISR , do you tell the PIC to print anything.
It's actually bad form to print within an ISR anyway, you should set a flag then have main() decide what to do with the flag.
Now if 'enter password' isn't being displayed on the LCD module, it's probably becuse you do not have a delay_ms(500) BEFORE the lcd_init() function. ALL LCD modules require time to 'boot/warm up/setup to default' BEFORE any micro sends commands to them. 500ms has been my standard delay for the past 25 years and every LCD module has worked fine after that delay.
Jay |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
variable number did not print on lcd |
Posted: Tue Oct 03, 2017 8:29 pm |
|
|
Thank you friend for your help!
I was able to find the error. The error was in the print function. Substituting the command for:
Code: |
lcd_gotoxy (7.2);
if (number == 11) printf (lcd_putc, "*");
else if (number == 12) printf (lcd_putc, "#");
else printf (lcd_putc, "% u", number);
|
It worked in my code.
Code: |
while(1)
{
//waiting for interruption timer0
}// End while(true)
|
Now number is printed on the LCD according to the key pressed and led3 flashes the number set to number.
Now I will continue developing the code. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9100 Location: Greensville,Ontario
|
|
Posted: Wed Oct 04, 2017 7:53 am |
|
|
OK, Now I see that the ISR calls the 'pulse' function which has the printing inside it.
It is seriously BAD to have any delays inside an ISR and those 400ms delays are really bad.
ISRs need to be small and fast! Simply set a flag or two and get out, letting main() decide what to do otherwise the ISr will never work properly and you'll miss data or get erratic operation.
Jay |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
|
Posted: Wed Oct 04, 2017 8:47 pm |
|
|
Ok thanks temtronic, thank you very much. but as an implement this is your tip: "Simply set the flag or two and get out, letting main () decide what to do otherwise." Would it be using 2 clocks?
The intention of putting these 400ms in led3 was for testing only. But I would liked it be using 2 clocks.
now I'm creating another function below the void pulse (char keykeypad) called void inputpassword (void). but the program is only executing void pulse (char keykeypad), the new function "void inputpassword (void)" will read the password saved in a vector n [5] and check if the input is right or wrong. I declare the prototype of the new function, but the program does not execute the same one. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1316
|
|
Posted: Thu Oct 05, 2017 7:03 am |
|
|
Similar to the flag method, you can just put in a countdown variable in the ISR and use that in your main. For example, if I split out most of your ISR code into a separate function...we'll call it do stuff...and use a countdown variable:
Code: |
#define CONT_DEFAULT 17
char cont = CONT_DEFAULT;
#int_timer0
void TIMER0(void)
{
// 250*0,2us*256(prescaler)= 13ms
//this just causes a count down from whatever value you wanted.
if(cont){
cont--;
}
}
void do_stuff(){
output_toggle(Led1);
if(input(col0) && control == 0x01) // column 1 at high level? control equal to 1?
{
control = 0x02;
output_low(col0);
output_high(col1);
output_high(col2);
if (!input(row0)) pulse(1);
else if (!input(row1)) pulse (4);
else if (!input(row2)) pulse (7);
else if (!input(row3)) pulse (11);
}
else if(input(col1)&& control == 0x02)
{
control = 0x03;
output_high(col0);
output_low (col1);
output_high(col2);
if (!input(row0)) pulse(2);
else if (!input(row1)) pulse (5);
else if (!input(row2)) pulse (8);
else if (!input(row3)) pulse (0);
}
else if(input(col2)&& control == 0x03)
{
control = 0x01;
output_high(col0);
output_high(col1);
output_low(col2);
if (!input(row0)) pulse(3);
else if (!input(row1)) pulse (6);
else if (!input(row2)) pulse (9);
else if (!input(row3)) pulse (12);
} // End Else If
}
|
Then in your main, you can check the count down variable until it is 0 and then call do_stuff. Like this:
Code: |
void main(void)
{
set_tris_a(0b00000001);//RA0 as input.
set_tris_c(0x00);
set_tris_d(0x0f);
set_tris_e(0x00);// Port_E as output
output_a(0x00);
output_c(0x07);
output_d(0x0f);
output_E(0x02);
setup_timer_0(rtcc_internal|rtcc_div_256);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
set_timer0(0);
lcd_init();
lcd_putc("\fEnter password:");
while(1) //
{
while(cont); //loop until cont is 0, then continue
cont = CONT_DEFAULT; //reset to start over for next pass
do_stuff();
}// End while(true)
}// End da main
|
This will have a similar effect to your code without bogging down the ISR at all.
Note that I don't have a compiler in front of me to verify if this compiles. The idea should be ok, but you may have to tweak it if I miss copy/pasted.
Last edited by jeremiah on Wed Oct 18, 2017 1:59 pm; edited 1 time in total |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
|
Posted: Thu Oct 05, 2017 7:23 am |
|
|
Thank you very much friend jeremiah. I'll work on that example. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1316
|
|
Posted: Fri Oct 06, 2017 7:53 am |
|
|
jacktaylor wrote: | Thank you very much friend jeremiah. I'll work on that example. |
One correction. I accidentally used a while loop in the ISR. I meant it to be an IF statement:
Code: |
#int_timer0
void TIMER0(void)
{
// 250*0,2us*256(prescaler)= 13ms
//this just causes a count down from whatever value you wanted.
if(cont){
cont--;
}
}
|
my apologies. |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
variable bitest3 does not go to 1. |
Posted: Sun Oct 15, 2017 1:25 pm |
|
|
Hello friends, I am doing a program for the clock. I'm having a problem with a variable that does not update its value by pressing the adj_watch button. Can anyone tell me why the value of variable bitest3 does not go to one while pressing the adj_watch button inside the void function Set _watch ()? The variable remains with the value zero. This is only part of the program. PIN_D6 is just an LED to test the program's input into the function.
Code: |
#define adj_watch PIN_B4;
char control_adj_watch = 0x05;
void Set _watch () // Set watch
{
char bitest3= 0x00;
if(input(adj_watch))
{
bitest3= 0x01;
}
if(!input(adj_watch) && bitest3==1)
{
bitest3= 0x00;
control_adj_watch++; // Increment adjustment control variable
output_high(PIN_D6);
delay_ms(10500);
output_low(PIN_D6);
delay_ms(500);
// Restarts control variable if it is greater than 4:
if(control_adj_watch > 0x04) control_adj_watch = 0x00;
} //end if adj_watch
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19217
|
|
Posted: Sun Oct 15, 2017 1:39 pm |
|
|
Several separate things that may be causing problems:
What pulls the pin up?. Remember a button needs a pull up resistor...
Big problem though is timing and the variable.
You arrive in the routine. Bittest3 is set to '0'.
If it sees the pin go high Bittest3 gets set to 1.
It'll only proceed into the next part if this is '1', and the input is low (remember it is low to set Bitest to 1...). Unless the input drops exactly in the few uSec between the first test and the second, this will never happen. |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
Thank you Ttelmah |
Posted: Mon Oct 16, 2017 11:57 am |
|
|
Obrigado Ttelmah.
It's true, you're right, I've seen the mistake. I modified the code. Now start bitest3 = 0x01 and when the button is pressed the same goes to zero.
What does the pin up? Pin B4 starts at 1 through a pull-up resistor. The side of the resistor that is connected to the Pin is also connected to a button, this button is connected to the GND. That is, the resistor is pull-up and when the button is pressed, it sends GND to the input B4.
I'll sequence my code. Thank you for your big help.
Code: |
#define adj_watch PIN_B4;
char control_adj_watch = 0x05;
void Set _watch () // Set watch
{
char bitest3= 0x01;
if(!input(adj_watch) && bitest3==1)
{
bitest3= 0x00;
control_adj_watch++; // Increment adjustment control variable
output_high(PIN_D6);
delay_ms(1000);
output_low(PIN_D6);
delay_ms(500);
// Restarts control variable if it is greater than 4:
if(control_adj_watch > 0x04) control_adj_watch = 0x00;
} //end if adj_watch |
|
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
Assign value to the bit of a declared variable. |
Posted: Wed Oct 18, 2017 1:22 pm |
|
|
Hi friends, I have one more doubt.
When declaring a variable for example:
char test, an 8-bit memory space is reserved for this variable. The question is: How to set a value for a given bit of this variable? If I needed to put 1 only in bit 4 of the variable test What would be the command?
I know there is the #bit directive in ccs, which can be used for example with the PORT_A bits: #bit ra0 = 0x05.0; #bit ra1 = 0x05.1; #bit ra2 = 0x05.1; or with registers #bit T0IF = 0x b.2. But I do not know how to direct to the specific bit of the variable declared char test bit 4.
Could you help me how would it be? |
|
|
|