Bonjour à tous
Je suis nouveau sur le forum et je n'ai que des notions en programmation.
L'une de mes passions et l’électronique, que je pratique sur mes temps libre.
J'utilise MPLAB couplé à CCS .
J'ai déjà utilisé : les timers , les CAN , Interruptions, ... sur des PIC le tout en langage c.
J'ai fait l’acquisition du écran lcd MC42003A6W sur le site farnell ( lien avec datasheet : http://fr.farnell.com/midas/mc42004a...b-l/dp/2063162 ).
Après de longue recherche je me suis tourné vers le driver Flex_LCD420.c disponible sur le site de ccs. ( http://www.ccsinfo.com/forum/viewtopic.php?t=28268 )
Ce qui ma donner le code suivant:
driver:
Code:// Flex_LCD420.c // These pins are for my Microchip PicDem2-Plus board, // which I used to test this driver. // An external 20x4 LCD is connected to these pins. // Change these pins to match your own board's connections. #define LCD_DB4 PIN_B0 #define LCD_DB5 PIN_B1 #define LCD_DB6 PIN_B2 #define LCD_DB7 PIN_B4 #define LCD_RS PIN_A3 #define LCD_RW PIN_A2 #define LCD_E PIN_A4 /* // To prove that the driver can be used with random // pins, I also tested it with these pins: #define LCD_DB4 PIN_D4 #define LCD_DB5 PIN_B1 #define LCD_DB6 PIN_C5 #define LCD_DB7 PIN_B5 #define LCD_RS PIN_E2 #define LCD_RW PIN_B2 #define LCD_E PIN_D6 */ // If you want only a 6-pin interface to your LCD, then // connect the R/W pin on the LCD to ground, and comment // out the following line. Doing so will save one PIC // pin, but at the cost of losing the ability to read from // the LCD. It also makes the write time a little longer // because a static delay must be used, instead of polling // the LCD's busy bit. Normally a 6-pin interface is only // used if you are running out of PIC pins, and you need // to use as few as possible for the LCD. #define USE_RW_PIN 1 // These are the line addresses for most 4x20 LCDs. #define LCD_LINE_1_ADDRESS 0x00 #define LCD_LINE_2_ADDRESS 0x40 #define LCD_LINE_3_ADDRESS 0x14 #define LCD_LINE_4_ADDRESS 0x54 // These are the line addresses for LCD's which use // the Hitachi HD66712U controller chip. /* #define LCD_LINE_1_ADDRESS 0x00 #define LCD_LINE_2_ADDRESS 0x20 #define LCD_LINE_3_ADDRESS 0x40 #define LCD_LINE_4_ADDRESS 0x60 */ int8 i; int8 b1, b2, b3, b4; //======================================== #define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines(or more) int8 lcd_line; int8 const LCD_INIT_STRING[4] = { 0x20 | (lcd_type << 2), // Set mode: 4-bit, 2+ lines, 5x8 dots 0xc, // Display on 1, // Clear display 6 // Increment cursor }; //------------------------------------- void lcd_send_nibble(int8 nibble) { // Note: !! converts an integer expression // to a boolean (1 or 0). output_bit(LCD_DB4, !!(nibble & 1)); output_bit(LCD_DB5, !!(nibble & 2)); output_bit(LCD_DB6, !!(nibble & 4)); output_bit(LCD_DB7, !!(nibble & 8)); delay_cycles(1); output_high(LCD_E); delay_us(2); output_low(LCD_E); } //----------------------------------- // This sub-routine is only called by lcd_read_byte(). // It's not a stand-alone routine. For example, the // R/W signal is set high by lcd_read_byte() before // this routine is called. #ifdef USE_RW_PIN int8 lcd_read_nibble(void) { int8 retval; // Create bit variables so that we can easily set // individual bits in the retval variable. #bit retval_0 = retval.0 #bit retval_1 = retval.1 #bit retval_2 = retval.2 #bit retval_3 = retval.3 retval = 0; output_high(LCD_E); delay_us(1); retval_0 = input(LCD_DB4); retval_1 = input(LCD_DB5); retval_2 = input(LCD_DB6); retval_3 = input(LCD_DB7); output_low(LCD_E); delay_us(1); return(retval); } #endif //--------------------------------------- // Read a byte from the LCD and return it. #ifdef USE_RW_PIN int8 lcd_read_byte(void) { int8 low; int8 high; output_high(LCD_RW); delay_cycles(1); high = lcd_read_nibble(); low = lcd_read_nibble(); return( (high<<4) | low); } #endif //---------------------------------------- // Send a byte to the LCD. void lcd_send_byte(int8 address, int8 n) { output_low(LCD_RS); #ifdef USE_RW_PIN while(bit_test(lcd_read_byte(),7)) ; #else delay_us(60); #endif if(address) output_high(LCD_RS); else output_low(LCD_RS); delay_cycles(1); #ifdef USE_RW_PIN output_low(LCD_RW); delay_cycles(1); #endif output_low(LCD_E); lcd_send_nibble(n >> 4); lcd_send_nibble(n & 0xf); } //---------------------------- void lcd_init(void) { int8 i; lcd_line = 1; output_low(LCD_RS); #ifdef USE_RW_PIN output_low(LCD_RW); #endif output_low(LCD_E); // Some LCDs require 15 ms minimum delay after // power-up. Others require 30 ms. I'm going // to set it to 35 ms, so it should work with // all of them. delay_ms(35); for(i=0 ;i < 3; i++) { lcd_send_nibble(0x03); delay_ms(5); } lcd_send_nibble(0x02); for(i=0; i < sizeof(LCD_INIT_STRING); i++) { lcd_send_byte(0, LCD_INIT_STRING[i]); // If the R/W signal is not used, then // the busy bit can't be polled. One of // the init commands takes longer than // the hard-coded delay of 50 us, so in // that case, lets just do a 5 ms delay // after all four of them. #ifndef USE_RW_PIN delay_ms(5); #endif } } //---------------------------- void lcd_gotoxy(int8 x, int8 y) { int8 address; switch(y) { case 1: address = LCD_LINE_1_ADDRESS; break; case 2: address = LCD_LINE_2_ADDRESS; break; case 3: address = LCD_LINE_3_ADDRESS; break; case 4: address = LCD_LINE_4_ADDRESS; break; default: address = LCD_LINE_1_ADDRESS; break; } address += x-1; lcd_send_byte(0, 0x80 | address); } //----------------------------- void lcd_putc(char c) { switch(c) { case '\f': lcd_send_byte(0,1); lcd_line = 1; delay_ms(2); break; case '\n': lcd_gotoxy(1, ++lcd_line); break; case '\b': lcd_send_byte(0,0x10); break; default: lcd_send_byte(1,c); break; } } //------------------------------ #ifdef USE_RW_PIN char lcd_getc(int8 x, int8 y) { char value; lcd_gotoxy(x,y); // Wait until busy flag is low. while(bit_test(lcd_read_byte(),7)); output_high(LCD_RS); value = lcd_read_byte(); output_low(LCD_RS); return(value); } #endif
et pour le programme :
Code:void main() { // The lcd_init() function should always be called once, // near the start of your program. lcd_init(); // Clear the LCD. printf(lcd_putc, "\f"); delay_ms(500); while(1) { // Test the clear screen and newline commands. // Also test that we can write to all 4 lines. printf(lcd_putc, "\fThis is the 1st line"); printf(lcd_putc, "\nNext is the 2nd line"); printf(lcd_putc, "\nThis is the 3rd line"); printf(lcd_putc, "\nFinally the 4th line"); delay_ms(3000); // Test some additional characters. printf(lcd_putc, "\fABCDEFGHIJKLMNOPQRST"); printf(lcd_putc, "\nabcdefghijklmnopqrst"); printf(lcd_putc, "\n12345678901234567890"); printf(lcd_putc, "\n!@#$^&*(){}[]:;<>?/="); delay_ms(3000); // Clear the LCD. printf(lcd_putc, "\f"); delay_ms(500); // Test that lcd_gotoxy() works. Go to each of // the four corners and put a number in each one, // in a clockwise direction, starting with the upper // left corner. lcd_gotoxy(4, 2); printf(lcd_putc, "Put a number in"); lcd_gotoxy(4, 3); printf(lcd_putc, "each corner."); lcd_gotoxy(1, 1); printf(lcd_putc, "1"); lcd_gotoxy(20, 1); printf(lcd_putc, "2"); lcd_gotoxy(20, 4); printf(lcd_putc, "3"); lcd_gotoxy(1, 4); printf(lcd_putc, "4"); delay_ms(3000); // Read the character that was written in each corner // of the LCD and display it. This tests the lcd_getc() // function. // The following test can only be done if we can read // from the LCD. If the RW pin is not used, then the // LCD is in write-only mode, and we can't do this test. // The #ifdef statement will prevent the code from // being compiled, in that case. #ifdef USE_RW_PIN // Test if lcd_getc() can read // a byte from each corner. b1 = lcd_getc(1,1); b2 = lcd_getc(20,1); b3 = lcd_getc(20,4); b4 = lcd_getc(1,4); lcd_gotoxy(1, 1); printf(lcd_putc, "\fRead these bytes\n"); printf(lcd_putc, "from the 4 corners:\n\n"); printf(lcd_putc, " %c %c %c %c", b1, b2, b3, b4); delay_ms(3000); #endif // Type some characters and backspace over them. printf(lcd_putc, "\fType characters and\n"); printf(lcd_putc, "backspace over them."); delay_ms(2000); // Go to end of 2nd line. lcd_gotoxy(20, 2); // Backspace over 2nd line. for(i = 0; i < 20; i++) { printf(lcd_putc," \b\b"); delay_ms(150); } // Go to end of first line. lcd_gotoxy(20, 1); // Backspace over first line. for(i = 0; i < 20; i++) { printf(lcd_putc," \b\b"); delay_ms(150); } } }
Mais le code ne fonctionne pas.
J'ai donc modifié le init_lcd()
pour y ajouter setfunction, display off , display clear, Entry mode set.
Le souci et que cela ne fonctionne pas.Code:void lcd_init(void) { int8 i; lcd_line = 1; output_low(LCD_RS); #ifdef USE_RW_PIN output_low(LCD_RW); #endif output_low(LCD_E); // Some LCDs require 15 ms minimum delay after // power-up. Others require 30 ms. I'm going // to set it to 35 ms, so it should work with // all of them. delay_ms(35); for(i=0 ;i < 3; i++) { lcd_send_nibble(0x03); delay_ms(5); } lcd_send_nibble(0x02); lcd_send_nibble(0b001010); // setfunction delay_ms(5); lcd_send_nibble(0b00001000); // display off delay_ms(5); lcd_send_nibble(0b00000001); // display clear delay_ms(5); lcd_send_nibble(0b00000110); // Entry mode set delay_ms(5); for(i=0; i < sizeof(LCD_INIT_STRING); i++) { lcd_send_byte(0, LCD_INIT_STRING[i]); // If the R/W signal is not used, then // the busy bit can't be polled. One of // the init commands takes longer than // the hard-coded delay of 50 us, so in // that case, lets just do a 5 ms delay // after all four of them. #ifndef USE_RW_PIN delay_ms(5); #endif } }
Le lcd reste impassible avec la 1er et 3eme ligne remplies de petits carrées (5x8) et la 2eme et 4 eme sont vides.
Il s'agit du premier driver que j'utilise et j'ai du mal a tout comprendre .
J'ai également tenté de réaliser un petit driver qui affiche la lettre A sur la ligne 1 case 1 du lcd sans suces non plus.
Auriez vous une petits idées ?
-----