xpress_embedo
Advanced Member level 4
Hello! Everyone
Checking busy flag with 4 bit of 16x2 lcd is discussed in various post of this forum and i have taken reference of these post and wrote the code for lcd 4 bit mode and checking the busy flag.
Reference Taken from this post.
https://www.edaboard.com/threads/250386/
If i use delay, lcd is working in 4-bit mode properly but when i use the busy flag it doesn't work and i am getting the following error in proteus.
[HD44780] Attempted to read after writing a single nibble [LCD1]
Can someone please look at my code and point at the mistake which i have done.
I am using PIC18F45k50 micro-controller with XC8 compiler and MPLABX IDE (The program is tested on real hardware as well and even on that it is not working with busy flag check, but working with delay)
Busy Flag code is:
The Complete code is as follow:
In my project, i can't use lcd in 4-bit mode with delay as it is taking too much time and delaying other things.
I am also attaching my project and proteus simulation in a zip folder.
LCD Working in 4-bit mode with delay, image shown below:
Thanks in advance.
Checking busy flag with 4 bit of 16x2 lcd is discussed in various post of this forum and i have taken reference of these post and wrote the code for lcd 4 bit mode and checking the busy flag.
Reference Taken from this post.
https://www.edaboard.com/threads/250386/
If i use delay, lcd is working in 4-bit mode properly but when i use the busy flag it doesn't work and i am getting the following error in proteus.
[HD44780] Attempted to read after writing a single nibble [LCD1]
Can someone please look at my code and point at the mistake which i have done.
I am using PIC18F45k50 micro-controller with XC8 compiler and MPLABX IDE (The program is tested on real hardware as well and even on that it is not working with busy flag check, but working with delay)
Busy Flag code is:
Code C - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 void lcd_busy( void ) { uint32_t timeout = 0u; uint8_t value; lcd_initialized = TRUE; // Become False if, initialization fails LCD_BUSY_PIN_DIR = 1; // Make Busy Pin as Input. LCD_RS = 0; LCD_RW = 1; value = LCD_BUSY_PIN; while( value ) { LCD_EN = 1; Nop(); Nop(); value = LCD_BUSY_PIN; Nop(); LCD_EN = 0; Nop(); Nop(); Nop(); Nop(); LCD_EN = 1; Nop(); Nop(); // value = LCD_BUSY_PIN; Nop(); LCD_EN = 0; timeout++; if( timeout > 2500u) { lcd_initialized = FALSE; break; } } LCD_BUSY_PIN_DIR = 0; // Make Busy Pin as Output. LCD_RS = 0; }
The Complete code is as follow:
Code C - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 #pragma config PLLSEL = PLL4X // PLL Selection (4x clock multiplier) #pragma config CFGPLLEN = OFF // PLL Enable Configuration bit (PLL Disabled (firmware controlled)) #pragma config CPUDIV = NOCLKDIV// CPU System Clock Postscaler (CPU uses system clock (no divide)) #pragma config LS48MHZ = SYS24X4// Low Speed USB mode with 48 MHz system clock (System clock at 24 MHz, USB clock divider is set to 4) // CONFIG1H // #pragma config FOSC = INTOSCIO // Oscillator Selection (Internal oscillator) #pragma config FOSC = INTOSCCLKO // Oscillator Selection (Internal oscillator) #pragma config PCLKEN = ON // Primary Oscillator Shutdown (Primary oscillator enabled) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor (Fail-Safe Clock Monitor disabled) #pragma config IESO = OFF // Internal/External Oscillator Switchover (Oscillator Switchover mode disabled) // CONFIG2L #pragma config nPWRTEN = OFF // Power-up Timer Enable (Power up timer disabled) #pragma config BOREN = SBORDIS // Brown-out Reset Enable (BOR enabled in hardware (SBOREN is ignored)) #pragma config BORV = 190 // Brown-out Reset Voltage (BOR set to 1.9V nominal) #pragma config nLPBOR = OFF // Low-Power Brown-out Reset (Low-Power Brown-out Reset disabled) // CONFIG2H #pragma config WDTEN = OFF // Watchdog Timer Enable bits (WDT disabled in hardware (SWDTEN ignored)) #pragma config WDTPS = 32768 // Watchdog Timer Postscaler (1:32768) // CONFIG3H #pragma config CCP2MX = RC1 // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1) #pragma config PBADEN = OFF // PORTB A/D Enable bit (PORTB<5:0> pins are configured as digital I/O on Reset) #pragma config T3CMX = RC0 // Timer3 Clock Input MUX bit (T3CKI function is on RC0) #pragma config SDOMX = RB3 // SDO Output MUX bit (SDO function is on RB3) #pragma config MCLRE = ON // Master Clear Reset Pin Enable (MCLR pin enabled; RE3 input disabled) // CONFIG4L #pragma config STVREN = ON // Stack Full/Underflow Reset (Stack full/underflow will cause Reset) #pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled) #pragma config ICPRT = OFF // Dedicated In-Circuit Debug/Programming Port Enable (ICPORT disabled) #pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled) // CONFIG5L #pragma config CP0 = OFF // Block 0 Code Protect (Block 0 is not code-protected) #pragma config CP1 = OFF // Block 1 Code Protect (Block 1 is not code-protected) #pragma config CP2 = OFF // Block 2 Code Protect (Block 2 is not code-protected) #pragma config CP3 = OFF // Block 3 Code Protect (Block 3 is not code-protected) // CONFIG5H #pragma config CPB = OFF // Boot Block Code Protect (Boot block is not code-protected) #pragma config CPD = OFF // Data EEPROM Code Protect (Data EEPROM is not code-protected) // CONFIG6L #pragma config WRT0 = OFF // Block 0 Write Protect (Block 0 (0800-1FFFh) is not write-protected) #pragma config WRT1 = OFF // Block 1 Write Protect (Block 1 (2000-3FFFh) is not write-protected) #pragma config WRT2 = OFF // Block 2 Write Protect (Block 2 (04000-5FFFh) is not write-protected) #pragma config WRT3 = OFF // Block 3 Write Protect (Block 3 (06000-7FFFh) is not write-protected) // CONFIG6H #pragma config WRTC = OFF // Configuration Registers Write Protect (Configuration registers (300000-3000FFh) are not write-protected) #pragma config WRTB = OFF // Boot Block Write Protect (Boot block (0000-7FFh) is not write-protected) #pragma config WRTD = OFF // Data EEPROM Write Protect (Data EEPROM is not write-protected) // CONFIG7L #pragma config EBTR0 = OFF // Block 0 Table Read Protect (Block 0 is not protected from table reads executed in other blocks) #pragma config EBTR1 = OFF // Block 1 Table Read Protect (Block 1 is not protected from table reads executed in other blocks) #pragma config EBTR2 = OFF // Block 2 Table Read Protect (Block 2 is not protected from table reads executed in other blocks) #pragma config EBTR3 = OFF // Block 3 Table Read Protect (Block 3 is not protected from table reads executed in other blocks) // CONFIG7H #pragma config EBTRB = OFF // Boot Block Table Read Protect (Boot block is not protected from table reads executed in other blocks) #include <xc.h> #include <stdint.h> #define _XTAL_FREQ 16000000UL #define USE_LCD_BUSY_FLAG /**< Use Busy Bit instead of Delay.*/ #define LCD_DATA LATD /**< LCD Data Port.*/ #define LCD_DATA_DIR TRISD /**< LCD Data Direction Register.*/ #define LCD_BUSY_PIN PORTDbits.RD7 /**< LCD Busy Pin.*/ #define LCD_BUSY_PIN_DIR TRISD7 /**< LCD Busy Pin Direction.*/ #define LCD_RS LATB2 /**< LCD RS Pin.*/ #define LCD_RS_DIR TRISB2 /**< LCD RS Direction.*/ #define LCD_RW LATB4 /**< LCD RW Pin.*/ #define LCD_RW_DIR TRISB4 /**< LCD RW Direction.*/ #define LCD_EN LATB5 /**< LCD EN Pin.*/ #define LCD_EN_DIR TRISB5 /**< LCD EN Direction.*/ /* LCD Commands */ #define LCD_16x2_INIT 0x38 /**< Initialize 16x2 Lcd in 8-bit Mode.*/ #define LCD_16x1_INIT 0x03 /**< Initialize 16x1 Lcd in 8-bit Mode.*/ #define LCD_16x1_INIT_4BIT 0x02 /**< Initialize 16x1 Lcd in 4-bit Mode.*/ #define LCD_16x2_INIT_4BIT 0x28 /**< Initialize 16x2 Lcd in 4-bit Mode.*/ #define LCD_DISP_ON_CUR_ON 0x0E /**< LCD Display On Cursor On.*/ #define LCD_DISP_ON_CUR_OFF 0x0C /**< LCD Display On Cursor Off.*/ #define LCD_DISP_ON_CUR_BLNK 0x0F /**< LCD Display On Cursor Blink.*/ #define LCD_ENTRY_MODE 0x06 /**< LCD Entry Mode. */ #define LCD_FIRST_ROW 0x80 /**< Move Pointer to First Row.*/ #define LCD_SECOND_ROW 0xC0 /**< Move Pointer to Second Row.*/ #define LCD_CLEAR 0x01 /**< Clear LCD Display.*/ #define TRUE 0xFF #define FALSE 0x00 static uint8_t lcd_initialized = FALSE; /**< LCD Initializatin Status.*/ #ifdef USE_LCD_BUSY_FLAG void lcd_busy(void); #endif /* LCD Function Prototypes */ void LCD_Init(void); void LCD_Cmd(uint8_t command); void LCD_Write(uint8_t Data); void LCD_Write_Text(char *msg); void main( void ) { // Select 16MHz Internal Oscillator OSCCONbits.IRCF = 0x07; // From 1MHz to 16MHz __delay_ms(2); LCD_Init(); __delay_ms(2); LCD_Write ('A'); LCD_Cmd (LCD_SECOND_ROW); LCD_Write_Text ((char*)"EDA Board"); while(1); } /** * @brief Initialize 16x2 LCD Module. * * Initialize 16x2 LCD Module in 4-bit mode. * */ #define LCD_MODE_4BIT void LCD_Init(void) { #ifndef USE_LCD_BUSY_FLAG lcd_initialized = TRUE; // Set to True if using delay mode #endif // Set the LCD Pins as Output Pins LCD_DATA_DIR &= 0x0F; // Set LCD Control Pins as Output Pins LCD_RS_DIR = 0; // RS LCD_RW_DIR = 0; // RW LCD_EN_DIR = 0; // EN // Set Back-Lit Pin as Output (If Present) // Clear Values ANSELD &= ~(0x80); LCD_DATA &= 0x0F; LCD_RS = 0; LCD_RW = 0; LCD_EN = 0; // Clear Back-Lit #ifdef USE_LCD_BUSY_FLAG lcd_busy(); #else __delay_ms(2); #endif __delay_ms(10); __delay_ms(10); LCD_Cmd(LCD_16x1_INIT); __delay_ms(10); LCD_Cmd(LCD_16x1_INIT); __delay_ms(10); LCD_Cmd(LCD_16x1_INIT); __delay_ms(10); LCD_Cmd(LCD_16x1_INIT_4BIT); __delay_ms(10); LCD_Cmd(LCD_16x2_INIT_4BIT); LCD_Cmd(LCD_DISP_ON_CUR_ON); LCD_Cmd(LCD_DISP_ON_CUR_OFF); LCD_Cmd(LCD_CLEAR); LCD_Cmd(LCD_ENTRY_MODE); LCD_Cmd(LCD_FIRST_ROW); } /** * @brief Send Command to LCD. * * Send Command to LCD, use the following commands. * <b>LCD_16x2_INIT,LCD_DISP_ON_CUR_ON,LCD_DISP_ON_CUR_OFF,LCD_DISP_ON_CUR_BLNK, * LCD_FIRST_ROW,LCD_SECOND_ROW,LCD_CLEAR</b>. * @param command Command to Send to the LCD. */ void LCD_Cmd(uint8_t command) { LCD_DATA &= 0x0F; // Clear Data LCD_DATA |= (command & 0xF0); LCD_RS = 0; LCD_RW = 0; LCD_EN = 1; Nop(); Nop(); LCD_EN = 0; #ifdef USE_LCD_BUSY_FLAG lcd_busy(); #else __delay_ms(2); #endif LCD_DATA &= 0x0F; // Clear Data LCD_DATA |= ((command<<4) & 0xF0); LCD_EN = 1; Nop(); Nop(); LCD_EN = 0; #ifdef USE_LCD_BUSY_FLAG lcd_busy(); #else __delay_ms(2); #endif } /** * @brief Write Data on LCD. * * Write Data on LCD, specified as arguments. * @param Data Data to Write on LCD. */ void LCD_Write(uint8_t Data) { if( !lcd_initialized ) { LCD_Init(); // Re-Initialize LCD } if( lcd_initialized ) { LCD_DATA &= 0x0F; // Clear Data LCD_DATA |= (Data & 0xF0); LCD_RS = 1; LCD_RW = 0; LCD_EN = 1; Nop(); Nop(); LCD_EN = 0; #ifdef USE_LCD_BUSY_FLAG lcd_busy(); #else __delay_ms(2); #endif LCD_DATA &= 0x0F; // Clear Data LCD_DATA |= ((Data<<4) & 0xF0); LCD_EN = 1; Nop(); Nop(); LCD_EN = 0; #ifdef USE_LCD_BUSY_FLAG lcd_busy(); #else __delay_ms(2); #endif } } /** * @brief Write String on LCD. * * Write String on LCD, specified as arguments. * @param *msg First Character Address of the String. * @note String Must be terminated by NULL Character. */ void LCD_Write_Text(char *msg) { while(*msg) { LCD_Write(*msg); msg++; } } #ifdef USE_LCD_BUSY_FLAG /** * @brief Lcd Busy. * * Wait for LCD Controller to get Ready. * @note Timeout Counter is added to protect the system from hanging state. In * most of the cases timeout counter value is < 50 but as clear command takes * time, and at that point counter value is around < 1800. Things will change * with operating frequency of micro. Please re-evaluate the optimum value for * your setup. */ void lcd_busy( void ) { uint32_t timeout = 0u; uint8_t value; lcd_initialized = TRUE; // Become False if, initialization fails LCD_BUSY_PIN_DIR = 1; // Make Busy Pin as Input. LCD_RS = 0; LCD_RW = 1; value = LCD_BUSY_PIN; while( value ) { LCD_EN = 1; Nop(); Nop(); value = LCD_BUSY_PIN; Nop(); LCD_EN = 0; Nop(); Nop(); Nop(); Nop(); LCD_EN = 1; Nop(); Nop(); // value = LCD_BUSY_PIN; Nop(); LCD_EN = 0; timeout++; if( timeout > 2500u) { lcd_initialized = FALSE; break; } } LCD_BUSY_PIN_DIR = 0; // Make Busy Pin as Output. LCD_RS = 0; } #endif
In my project, i can't use lcd in 4-bit mode with delay as it is taking too much time and delaying other things.
I am also attaching my project and proteus simulation in a zip folder.
LCD Working in 4-bit mode with delay, image shown below:
Thanks in advance.