|
|
View previous topic :: View next topic |
Author |
Message |
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
LCD Do not initialize using PORTs A and E. |
Posted: Sat Sep 02, 2017 9:01 am |
|
|
Hello friends. I have a didatica board for studies that uses as configuration RS-> RE0, E-> RA5, D4-> RA4, D5-> RA3, D6-> RA2, D7-> RA1 to initialize the LCD.
CCS by default sets PORT_D in library #include <lcd.c>, it is easy to switch to PORT_B inserted in the #define directive use_portb_lcd true.
I made this code in the attempt to use the PORTs_A, E., but does not initialize the LCD. The ADCON1 recorder of the PIC 16F877A comes standard with all the bits zeroed, I believe it is necessary to configure the pins of the PIC as a digital output to use the LCD.
Please help me find the error?
Code: |
#include <16F877a.h>
#device ADC = 10 // 8-bit converter
#fuses hs, nowdt, nolvp
#use delay (clock = 20M)
#define use_porta_lcd true
#define use_porte_lcd true
#include <lcd.c>
#use fast_io (a)
#use fast_io (e)
#byte ADCON1 = 0x9F // register address ADCON1
Void main (void)
{
SETUP_ADC_PORTS (AN0);
Set_tris_a (0b00000001); // the first pin Analogic
Set_tris_e (0x11111110);
ADCON1 = 0b00001110;
Init_lcd ();
Printf (lcd_txt, "PIC and LCD");
Dealy_ms (3000);
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9249 Location: Greensville,Ontario
|
|
Posted: Sat Sep 02, 2017 9:55 am |
|
|
this...
is incorrect, compiler should complain about it....
Also If I recall correctly, the LCD.c driver requires that ALL lines connected to the LCD module be from ONE port, you've 'split' them...
It would be best to use the 'flex_lcd.c' driver, where you CAN 'split' the pins any way you want.
And with ANY I/O pin that has multiple uses, you should disable all peripherals associated with that pin (ADC, comparators, etc.).
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19554
|
|
Posted: Sat Sep 02, 2017 11:30 am |
|
|
Just to add to this. It is essential to read what the drivers say.
The #define use_porta_lcd true
Says to use port access for the LCD (so all the bits on one port), and put it on porta.
Similarly the next line says to use porte the same way....
Honestly, flex_lcd is the easier driver to setup, _but read what it says and set the pins up in the order you want_.
Think about it. How is the compiler meant to know what connects where on the two ports you are trying to use?.
As a comment, why are you accessing ADCON. Just use the compiler's instruction setup_adc. Much less likely to be wrong. You are currently setting the ADC to use Fosc/2, which has a maximum supported processor speed of 1.25Mhz. It is not going to give anything even remotely close to a correct reading...
setup_adc(ADC_CLOCK_DIV_32); |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
Thanks Friends. |
Posted: Tue Sep 12, 2017 10:16 am |
|
|
Now it worked with these settings. I am using the ports configured for the LCD and also the analog input on Port_a and E.
Code: |
#define LCD_DB4 PIN_A4 // Pinos bloco dados LCD deve ser definidos antes da biblioteca <lcd4bitsMicrostronic.c>
#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> // 'flex_lcd.c' driver
void main(){
set_tris_a(0b00000001);
set_tris_e(0x02);
set_tris_d(0x0F);
set_tris_c(0x07);
setup_adc_ports(an0);
setup_adc(ADC_CLOCK_INTERNAL );
set_adc_channel(0);
enable_interrupts(int_ad);
enable_interrupts(global);
lcd_init();
kbd_init();
lcd_putc("SENHA:\n"); // Escreve no LCD
} |
|
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
|
Posted: Tue Sep 12, 2017 10:35 am |
|
|
Ttelmah thank you friend: sorry I did not understand your question I'm starting to learn programming now, I have a lot of doubts on how to do it.
Quote: |
As a comment, why are you accessing ADCON. Just use the compiler's instruction setup_adc. Much less likely to be wrong. You are currently setting the ADC to use Fosc/2, which has a maximum supported processor speed of 1.25Mhz. It is not going to give anything even remotely close to a correct reading...
setup_adc(ADC_CLOCK_DIV_32);
|
But at first I accessed the ADCON1 to configure only the TRIS A1, A2, A3, A4, A5 for LCD, and A0 as analog. I did another test removing ADCON1 from the program, but I had to keep the command set_tris_a (0b00000001); because in it the LCD is not initializing.
This is my full program test:
Code: | #include <16f877a.h>
#device ADC = 10
#fuses hs, nowdt, nolvp, put, brownout
#use delay (clock=20M)
#use fast_io(a)
#use fast_io(e)
//#use fast_io(d)// para sensor temperatura
#define LCD_DB4 PIN_A4 // Pino bloco dados 4 no pino microcontrolador
#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>
//***Variaveis
//#byte ADCON1 = 0x9F
//int16 valor;
//int a = 25, b = 15;
void main()
{
//long data;
float temp, tensao, dados;
//ADCON1 = 0b00001110;
set_tris_a(0b00000001);
set_tris_e(0xFE); // 0b11111100
set_tris_d(0x00);//11110000
output_d(0x00);
SETUP_ADC(ADC_CLOCK_INTERNAL);
SETUP_ADC_PORTS(AN0);
SET_ADC_CHANNEL(0);
lcd_init();
while(1)
{
dados = (float) (READ_ADC());
delay_ms(50);
tensao = (5000.0*dados)/1024; // tensao em milivolts
temp = tensao/10;
//printf(lcd_putc,"\fVolt = %.1fmv", tensao);
//printf(lcd_putc,"\nTemp =%.1fGr ",temperatura);
delay_ms(1500);
if( temp<100)
{
output_high(pin_D4);
printf(lcd_putc,"\fTemperat Boa");
lcd_gotoxy(5,2);
printf(lcd_putc,"\%.1fGraus ", Temp);
delay_ms(100);
}
else
{
output_low(pin_D4);
}
if( temp>100&&temp<200)
{
output_high(pin_D5);
printf(lcd_putc,"\fTemperat Media");
printf(lcd_putc,"\n%.1fGraus ",Temp );
}
else
{
output_low(pin_D5);
}
if( temp>200&& temp<300)
{
output_high(pin_D6);
printf(lcd_putc,"\fTemperat Alta");
printf(lcd_putc,"\n%.1fGraus ",Temp );
}
else
{
output_low(pin_D6);
}
if( temp>300&&temp<=500)
{
output_high(pin_D7);
printf(lcd_putc,"\fTemperat Extrema");
printf(lcd_putc,"\n%.1fGraus ",Temp );
}
else
{
output_low(pin_D7);
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19554
|
|
Posted: Tue Sep 12, 2017 1:12 pm |
|
|
If you use flex_lcd, you don't have to configure TRIS. The standard CCS LCD driver directly accesses the port, and requires the TRIS setup. As you have found you don't need the ADCON setting, just the TRIS. |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
Keypad keyboard does not generate numbers correctly. |
Posted: Sun Sep 17, 2017 11:22 am |
|
|
Ttelmah thank you friend.
Now I have another problem. I used a flex library for the keypad. But when typing on the keypad the numbers do not match, for example the number one never appears even by pressing the 1 key, on the contrary 4 appears in another one pressed 5 appears and in the place of the number 6 appears the 9 or # is very confused. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19554
|
|
Posted: Sun Sep 17, 2017 12:13 pm |
|
|
If the keys are coming up incorrectly, then the physical connections you have do not match the pins you are specifying in the driver....
Remember also the row pins do need pull-ups. Either programmed in the chip or physical resistors. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9249 Location: Greensville,Ontario
|
|
Posted: Sun Sep 17, 2017 12:40 pm |
|
|
Mr t is spot on !
Sounds like you have the ROWs not connected correctly.
Row 1 has 1,2,3
Row 2 has 4,5,6
Row 3 has 7,8,9
Row 4 has *,0,#
Col 1 has 1,4,7,*
Col 2 has 2,5,8,0
Col 3 has 3,6,9,#
That's providing you follow the 'convention' that the #1 key (top left) of a KPD is the starting point. Nothing says you have to though.
Jay |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
keyboard scan by interruption timer0 |
Posted: Tue Sep 19, 2017 12:32 pm |
|
|
Many thanks for the help, friends !! No, but it seems to be the deboucyng effect, since I have corrected all the connections and even then the same key continues to generate several different numbers.
I am trying to make a program that sweeps the keyboard by interrupting the zero timer, because from what I researched it inhibits the deboucing effect !! This is program: This generates this error: "Expecting LVALUE such as a variable name or * expression" in all the lines with: Led1 = 0x01; and all lines with col0 = 0x01;
col1 = 0x00;
col2 = 0x01;
Can you help me friends!!
Code: |
#include <16f877a.h>
#fuses hs, nowdt, nolvp, put, brownout
#use delay (clock=20M)
#use fast_io(a)
#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>
#define col0 PIN_C0
#define col1 PIN_C1
#define col2 PIN_C2
#define row0 PIN_D0
#define row1 PIN_D1
#define row2 PIN_D2
#define row3 PIN_D3
#define Led1 PIN_D4
char control = 0x01;
char cont = 0x00;
//** interrupt timer directive
#int_timer0
//** Interrupt function due to TIMER0 overflow
void varre()
{
SET_TIMER0(0); // 256-0 = 250*0,2us*256(prescaler)= 13ms
cont++;
}
//void pulse function, the led flashes the number of times the key is pressed.. The value of number is the value assigned to the pulse when the line and column of the keypad
void pulse (char number)
{
char i;
for (i=0; i<number; i++)
{
Led1 = 0x01;
delay_ms (400);
Led1 = 0x00;
delay_ms (400);
}
}
// Home of main
void main(void)
{
setup_timer_0(rtcc_internal|rtcc_div_256);
enable_interrupts(global);
SET_TIMER0(0);
if (cont == 256) //Has the timer popped?
{
cont==0x00;
if(col0 && control == 0x01)
{
control = 0x02; // active control = 02 to exit this loop if
col0 = 0x00; //we want to turn column 1 on low level after pressing a button
col1 = 0x01;
col2 = 0x01;
if (!row0) pulse(1); // if it is line A, it will flash LED 1 time..pull (1)
else if (!row1) pulse (4); // if it is line B, it will flash LED 4 time..pull (4)
else if (!row2) pulse (7); // if it is line C, it will flash LED 7 time..pull (7)
else if (!row3) pulse (11); // // if it is line D, it will flash LED 11 time..pull (11)
}
else if(col1 && control == 0x02)
{
control = 0x03;
col0 = 0x01;
col1 = 0x00;
col2 = 0x01;
if (!row0) pulse(2);
else if (!row1) pulse (5);
else if (!row2) pulse (8);
else if (!row3) pulse (10);
}
else if(col2 && control == 0x03)
{
control = 0x01;
col0 = 0x01;
col1 = 0x01;
col2 = 0x00;
if (!row0) pulse(3);
else if (!row1) pulse (6);
else if (!row2) pulse (9);
else if (!row3) pulse (12);
}
}// End if keyboard scan
}// End main |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9249 Location: Greensville,Ontario
|
|
Posted: Tue Sep 19, 2017 2:36 pm |
|
|
1st problem.
You're using fast_io() but NOT configuring the tris registers, at least not that I can see in your program. Perhaps your LCD driver sets them? But we can't tell....
Have to ask why don't you use the flex_kbd driver? It works, even on an 18F46K22 running at 64MHz attached on a 20 year old breadboard!!
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Sep 19, 2017 5:42 pm |
|
|
Jack,
You need to do a lot of basic computer study. You're trying to do
programming without knowing the basics. This results in disaster.
Example:
Code: |
char cont = 0x00;
if (cont == 256) |
A char in CCS is an unsigned 8-bit number. It can only have
a value from 0 to 255. It can't ever be 256. Furthermore, Timer0 is
8 bits in the 16F877A. It can only count from 0 to 255. At 255, it rolls
over and starts counting up from 0 again.
Now let's look your next mistake:
Code: | if(col0 && control == 0x01) |
The && operator is a TRUE/FALSE operator. You're using it as if it's a
bitwise ANDing operator, and that is not the case. The bitwise ANDing
operator is a single ampersand: &
This is all basic bonehead C knowledge. You can't just jump into C
without learning all this stuff and whole lot more. You can't write PIC
code in C without carefully reading and remembering the PIC data sheet.
And then your posted complaint is:
Quote: | Expecting LVALUE such as a variable name or * expression" in all the lines with: Led1 = 0x01; and all lines with col0 = 0x01; |
You have got these defined as constants:
Code: | #define col0 PIN_C0
#define col1 PIN_C1
#define col2 PIN_C2 |
PIN_C0, etc., are just numbers. Look in the 16F877A.h file. It lists what
they are. i.e.:
Code: | #define PIN_C0 56
#define PIN_C1 57
#define PIN_C2 58
|
So in your program you are doing this:
Code: | col1 = 0x00;
col2 = 0x01; |
So you're trying to do this:
Code: |
57 = 0x00;
58 = 0x01; |
You have got to spend a lot more time learning how computers work and
how to program them before you can write code. |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
Thank temtronic |
Posted: Tue Sep 19, 2017 8:59 pm |
|
|
Thank you friend temtronic. I really wondered how to set up the TRIS. I'm starting to learn to program now and study alone for it so many doubts and mistakes. Yes I used the Flex kdb driver file. But I am trying to develop this code by scan to test, because my keypad has generated different numbers when triggering the same keys and with this I want to try to dim the debaucing effect by using the scan by the overflow of timer0. I will correct the program by setting the tris. Thank you very much. |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
Thank you PCM programmer |
Posted: Tue Sep 19, 2017 9:18 pm |
|
|
thanks friend PCM programmer for the clarifications and tips I'm starting to learn how to program now, so I have a lot of questions and mistakes. I have followed C programming manuals, CCS and PIC datasheet, but the content is quite extensive and complex and I have a long way to go to learn. I'm studying the few months. And I've dedicated myself. I'm sorry for the basic mistakes you've made, but I hope you understand that every initial apprenticeship is like that, with lots of mistakes. Thanks for the valuable tips. I will make the corrections and I know new doubts I will have.
Ok I understood your explanation and I open and saw file #include <16f877a.h>
So to make the column go to logical level zero the correct one is to use the command output_low (col0); and all other rows and columns correct?
I did not understand why CCS is assigned a constant to pins, registers and et all.
#define PIN_C0 56
#define PIN_C1 57
#define PIN_C2 58
Programming in the Mikroc the command col1 = 0x00;
is correct, that is, it compiles without any errors. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Sep 19, 2017 10:25 pm |
|
|
jacktaylor wrote: |
So to make the column go to logical level zero the correct one is to use
the command output_low (col0); and all other rows and columns correct? | Yes.
jacktaylor wrote: |
I did not understand why CCS is assigned a constant to pins, registers
#define PIN_C0 56
#define PIN_C1 57
#define PIN_C2 58
|
The number encodes the Port address and the bit position.
For example, 58 is the code for pin C2.
58 is 0x3A in hex, and 0b00111010 in binary.
The bottom 3 bits (010) are the bit number, and the upper 5 bits are
the port address. Below, you can see that the Port address is 7 and
the bit position is 2.
Code: |
Binary 00111 010
Decimal 7 2
|
Look at the 16F877A data sheet, at this table:
Quote: | FIGURE 2-3: PIC16F876A/877A REGISTER FILE MAP |
It lists the memory address of PortC as 7. Bit position 2 corresponds to
Pin C2 on Port C.
The compiler uses these encoded Port/Bit position values with these functions:
output_low()
output_high()
output_float()
output_toggle()
etc. |
|
|
|
|
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
|