Integrated programming of single chip microcomputer I2C and EEPROM
The memory function of TV channel, the setting of traffic light countdown time and the memory function of outdoor LED advertising may all use memory devices such as EEPROM. The advantage of such devices is that the stored data can not only be changed, but also the data will not be lost after power failure. Therefore, they are widely used in various electronic products.
Our routine in this class is a little similar to the advertising screen. After power on, the first line of 1602 displays 16 characters of EEPROM starting from 0x20 address, and the second line displays 16 characters of EERPOM starting from 0x40. We can change the data in EEPROM through UART serial communication, and also change the content displayed in 1602. The updated content will be displayed directly when we power on next time.
All the relevant contents of this program have been mentioned earlier. But this program is embodied in a comprehensive application capability. This program uses 1602 LCD, UART serial communication, EEPROM read-write operation and other comprehensive applications. It's easy to write a small light, but if we want to really learn MCU well, we must learn the application of this comprehensive program and realize multiple modules to participate in the work at the same time. Therefore, students should seriously establish the project, write the program line by line, and finally consolidate it.
/I2C.c file program source code * * / (omitted here, refer to the code in the previous chapter) / Lcd1602.c file program source code * * / (omitted here, refer to the code in the previous chapter) / eeprom.c file program source code / (omitted here, refer to the code in the previous chapter) / Uart.c file program source code * / (omitted here, refer to the code in the previous chapter)
/*****************************main.c File program source code******************************/ #include <reg52.h> unsigned char T0RH = 0; //High byte of T0 overload value unsigned char T0RL = 0; //Low byte of T0 overload value void InitShowStr(); void ConfigTimer0(unsigned int ms); extern void InitLcd1602(); extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str); extern void E2Read(unsigned char *buf, unsigned char addr, unsigned char len); extern void E2Write(unsigned char *buf, unsigned char addr, unsigned char len); extern void UartDriver(); extern void ConfigUART(unsigned int baud); extern void UartRxMonitor(unsigned char ms); extern void UartWrite(unsigned char *buf, unsigned char len); void main(){ EA = 1; //On total interrupt ConfigTimer0(1); //Configure T0 timing 1ms ConfigUART(9600); //The baud rate is 9600 InitLcd1602(); //Initialize LCD InitShowStr(); //Initial display content while (1){ UartDriver(); //Call serial driver } } /* Process the initial display content of LCD */ void InitShowStr(){ unsigned char str[17]; str[16] = '\0';//Add a string terminator at the end to ensure that the string can end E2Read(str, 0x20, 16); //Read the first line of string, and its E2 starting address is 0x20 LcdShowStr(0, 0, str); //Display to LCD E2Read(str, 0x40, 16); //Read the second line of string, and its E2 starting address is 0x40 LcdShowStr(0, 1, str); //Display to LCD } /* The memory comparison function compares whether the memory data pointed to by the two pointers are the same, ptr1-Pointer to be compared 1, ptr2 pointer to be compared 2, len length to be compared Return value - returns 1 when the two memory data are exactly the same, and 0 when different */ bit CmpMemory(unsigned char *ptr1, unsigned char *ptr2, unsigned char len){ while (len--){ if (*ptr1++ != *ptr2++){ //0 is returned immediately when unequal data is encountered return 0; } } return 1; //If all length data are equal after comparison, 1 is returned } /* Sort a string into a fixed length string of 16 bytes, and fill in spaces in the insufficient part out-Sorted string output pointer, in - string pointer to be sorted */ void TrimString16(unsigned char *out, unsigned char *in){ unsigned char i = 0; while (*in != '\0'){ //Copy the string until the end of the input string *out++ = *in++; i++; if (i >= 16){ //When the copy length has reached 16 bytes, the loop is forced to jump out break; } } for ( ; i<16; i++){ //If it is less than 16 bytes, fill it with spaces *out++ = ' '; } *out = '\0'; //Last add Terminator } /* The serial port action function executes the response action according to the received command frame buf-Received command frame pointer, len command frame length */ void UartAction(unsigned char *buf, unsigned char len){ unsigned char i; unsigned char str[17]; unsigned char code cmd0[] = "showstr1 "; //First line character display command unsigned char code cmd1[] = "showstr2 "; //Second line character display command unsigned char code cmdLen[] = { //Command length summary sizeof(cmd0)-1, sizeof(cmd1)-1, }; unsigned char code *cmdPtr[] = { //Command pointer summary &cmd0[0], &cmd1[0], }; for (i=0; i<sizeof(cmdLen); i++){ //Traverse the command list to find the same command if (len >= cmdLen[i]){ //First, the received data length should not be less than the command length if (CmpMemory(buf, cmdPtr[i], cmdLen[i])){ //Exit the loop at the same time break; } } } switch (i){ //Execute the corresponding command according to the comparison results case 0: buf[len] = '\0'; //Adds a terminator to the received string TrimString16(str, buf+cmdLen[0]); //Collate into 16 byte fixed length string LcdShowStr(0, 0, str); //Display string 1 E2Write(str, 0x20, sizeof(str)); //Save string 1, starting at 0x20 break; case 1: buf[len] = '\0'; //Adds a terminator to the received string TrimString16(str, buf+cmdLen[1]); //Collate into 16 byte fixed length string LcdShowStr(0, 1, str); //Display string 1 E2Write(str, 0x40, sizeof(str)); //Save string 2, starting at 0x40 break; default: //When no matching command is found, send the prompt of "wrong command" to the computer UartWrite("bad command.\r\n", sizeof("bad command.\r\n")-1); return; } buf[len++] = '\r'; //After the valid command is executed, it is added after the original command frame buf[len++] = '\n'; //After the carriage return line feed character is returned to the upper computer, it indicates that it has been executed UartWrite(buf, len); } /* Configure and start T0, ms-T0 timing time */ void ConfigTimer0(unsigned int ms){ unsigned long tmp; //Temporary variable tmp = 11059200 / 12; //Timer count frequency tmp = (tmp * ms) / 1000; //Calculate the required count value tmp = 65536 - tmp; //Calculate timer overload value tmp = tmp + 33; //Compensate the error caused by interrupt response delay T0RH = (unsigned char)(tmp>>8); //The timer overload value is split into high and low bytes T0RL = (unsigned char)tmp; TMOD &= 0xF0; //Clear the control bit of T0 TMOD |= 0x01; //Configure T0 to mode 1 TH0 = T0RH; //Load T0 overload value TL0 = T0RL; ET0 = 1; //Enable T0 interrupt TR0 = 1; //Start T0 } /* T0 Interrupt service function to execute serial port receiving monitoring and buzzer driving */ void InterruptTimer0() interrupt 1{ TH0 = T0RH; //Reload overloaded values TL0 = T0RL; UartRxMonitor(1); //Serial port receiving monitoring }
When we learn UART communication, we also use the IO port to simulate the UART communication process at the beginning, and finally realize the communication with the computer. Then, because STC89C52 has UART hardware communication module, we can easily realize the UART communication of single chip microcomputer directly through the configuration register. Similarly, if there is a hardware module inside the single chip microcomputer, the single chip microcomputer can directly and automatically realize I2C communication. We don't need to start, send and end the simulation of IO port simulation. After configuring the registers, the single chip microcomputer will do all these work.
However, our STC89C52 MCU does not have I2C hardware module, so if we use STC89C52 for I2C communication, we must use IO port to simulate. Using IO port to simulate I2C is actually more conducive to our thorough understanding of the essence of I2C communication. Of course, by learning the analog communication of IO port, if you encounter a single chip microcomputer with I2C module in the future, you should also do it easily. Using the internal hardware module can improve the execution efficiency of the program.