0. Introduction
For most MCUs, I2C has become a long-standing problem. Since the 51 era, software simulation of I2C has become the mainstream. Even today when ARMCortex M3 is popular, software simulation of I2C is still the most widely used method. Although software simulation can solve all problems, it always feels that the hardware resources inside the MCU are not fully utilized. After consulting all the books about the MSP430F5 series, there is no application code for hardware I2C. I have explored it through debugging, summarized my experience and shared it with you. I hope you like it. At the same time, the use of I2C can be divided into waiting method and interrupt method. From the perspective of understanding, the waiting method is clear and easy to use. From the perspective of power consumption, the interrupt method can flexibly enter the low power mode, but it is not easy to understand. This article starts with the waiting method.
The use of hardware I2C of the MSP430F5 series generally has the following problems:
[I2C address setting] Generally, the 7-bit address of I2C is written as 8-bit length, and the lowest bit is invalid. For example, the I2C address of AT24C02 is 0xA0, but the real 7-bit address is 0x50. And MSP430 needs to fill in the 7-bit address 0x50.
[I2C stop bit sending] During the I2C read operation, the MCU should send a no response to the slave after reading the last byte. The MSP430F5 series MCU will automatically complete the no response operation. This means that when reading the last byte, the stop bit related register should be operated first.
[I2C start bit transmission] If you carefully analyze the MSP430F5 reference manual, you will find that the I2C start bit is slightly different when sending read and write operations. When writing, you need to write data to TXBUF first, and then you can wait for the TXSTT flag to become 0, which is slightly different from the read and write operations.
【AT24C02 operation timing diagram】
view plain copy while( UCB0CTL1& UCTXSTP );
UCB0CTL1 |= UCTR; // write mode
UCB0CTL1 |= UCTXSTT; // Send start bit
// Wait for UCTXSTT=0 to change, but unfortunately the change will not be sent
while(UCB0IFG& UCTXSTT);
UCB0TXBUF = word_addr; // Send byte address
while( UCB0CTL1& UCTXSTP );
UCB0CTL1 |= UCTR; // write mode
UCB0CTL1 |= UCTXSTT; // Send start bit
// Wait for UCTXSTT=0 to change, but unfortunately the change will not be sent
while(UCB0IFG& UCTXSTT);
UCB0TXBUF = word_addr; // Send byte address
3. Write multiple bytes
3.1 Code Implementation
uint8_teeprom_writepage( uint8_t word_addr, uint8_t *pword_buf, uint8_t len)
{
while( UCB0CTL1& UCTXSTP );
UCB0CTL1 |= UCTR; // write mode
UCB0CTL1 |= UCTXSTT; // Send start bit
UCB0TXBUF = word_addr; // Send byte address
// Wait for UCTXIFG=1 and UCTXSTT=0 to change at the same time and wait for a flag bit
while(!(UCB0IFG& UCTXIFG))
{
if(UCB0IFG& UCNACKIFG) // If no response UCNACKIFG=1
{
return 1;
}
}
for( uint8_t i= 0; i < len; i++)
{
UCB0TXBUF = *pword_buf++; // Send register content
while(!(UCB0IFG& UCTXIFG)); // Wait until UCTXIFG=1
}
UCB0CTL1 |= UCTXSTP;
while(UCB0CTL1& UCTXSTP); // Wait for sending to complete
return 0;
}
3.2 Code Analysis
The multi-byte write function is similar to the single-byte write function and will not be explained in detail.
4. Read a single byte
The single-byte read function is the most complex of the four read and write functions. The reason for the complexity is that the UCTXSTP flag needs to be operated before reading the last byte.
4.1 Code Implementation
uint8_teeprom_readbyte( uint8_t word_addr, uint8_t *pword_value)
{
UCB0CTL1 |= UCTR; // write mode
UCB0CTL1 |= UCTXSTT; // Send start bit and write control byte
UCB0TXBUF = word_addr; //Send byte address, TXBUF must be filled first
// Wait for UCTXIFG=1 and UCTXSTT=0 to change at the same time and wait for a flag bit
while(!(UCB0IFG& UCTXIFG))
{
if(UCB0IFG& UCNACKIFG) // If no response UCNACKIFG=1
{
return 1;
}
}
UCB0CTL1 &= ~UCTR; //Read mode
UCB0CTL1 |= UCTXSTT; // Send start bit and read control byte
while(UCB0CTL1& UCTXSTT); // Wait until UCTXSTT=0
// If no response UCNACKIFG = 1
UCB0CTL1 |= UCTXSTP; //Send stop bit first
while(!(UCB0IFG& UCRXIFG)); // Read byte content
*pword_value = UCB0RXBUF; // Read BUF register after sending stop bit
while( UCB0CTL1& UCTXSTP );
return 0;
}
4.2 Code Analysis
This code gives the illusion that the MSP430 sends a stop bit first and then reads a byte. In fact, this is not the case. During an I2C read operation, after the host reads the last byte, it should send a no-acknowledgement NACK (no-acknowledgement is different from an acknowledgement) to the slave, and then the host sends a stop bit. In order to complete this combined action, the MSP430 requires the user to operate the UCTXSTP flag in advance, and perform a "combined action" of sending NACK and the I2C stop bit after reading RXBUF.
while(!(UCB0IFG& UCRXIFG));
*pword_value = UCB0RXBUF; // Read BUF register after sending stop bit
UCB0CTL1 |= UCTXSTP; // Send stop bit
The above code may cause subsequent I2C operations to fail.
5. Read multiple bytes
5.1 Code Implementation
uint8_t eeprom_readpage(uint8_t word_addr, uint8_t *pword_buf, uint8_t len )
{
while( UCB0CTL1& UCTXSTP );
UCB0CTL1 |= UCTR; // write mode
UCB0CTL1 |= UCTXSTT; // Send start bit and write control byte
UCB0TXBUF = word_addr; // Send byte address
// Wait for UCTXIFG=1 and UCTXSTT=0 to change at the same time and wait for a flag bit
while(!(UCB0IFG& UCTXIFG))
{
if(UCB0IFG& UCNACKIFG) // If no response UCNACKIFG=1
{
return 1;
}
}
UCB0CTL1 &= ~UCTR; // Read mode
UCB0CTL1 |= UCTXSTT; // Send start bit and read control byte
while(UCB0CTL1& UCTXSTT); // Wait until UCTXSTT=0
// If no response UCNACKIFG = 1
for( uint8_t i= 0; i< len -1; i++)
{
while(!(UCB0IFG& UCRXIFG)); // Read byte content, excluding the last byte content
*pword_buf++= UCB0RXBUF;
}
UCB0CTL1 |= UCTXSTP; // Send stop bit before receiving the last byte
while(!(UCB0IFG& UCRXIFG)); // Read the last byte
*pword_buf = UCB0RXBUF;
while( UCB0CTL1& UCTXSTP );
return 0;
}
5.2 Code Analysis
Reading a single byte is similar to writing a single byte. The only thing to note is that the write operation needs to fill the TXBUF first, while the read operation does not have this problem. Imagine that when an I2C write operation is performed, a byte of content must be written to the I2C slave, so it is reasonable to fill the TXBUF first. After filling the TXBUF, the MSP430 will perform a series of actions - sending the I2C start bit, the I2C read controller, and writing the first byte of the slave.
6 Unit Testing
The unit test is divided into two parts. The single-byte write function and the single-byte read function are grouped together. First, use the single-byte write function to write something to a certain address, and then use the single-byte read function to read something. If the written parameters are the same as the read content, the test passes. The multi-byte write function and the multi-byte read function are grouped together. The test process is similar, except that the content written changes from one to 8 consecutive bytes. Please note that the page size of AT24C02 is 8. If starting from the page header address, the maximum number of bytes to write is 8.
In addition, there needs to be a 10ms delay after the EEPROM write operation, otherwise the write and read operations will not be possible. Please refer to the AT24C02 data sheet for details.
6.1 Test Code
void eeprom_config()
{
#ifDEBUF_EEPROM_I2C
uint8_t test_byte1 =0x0B;
uint8_t test_byte2 = 0x01;
/*
Step 1 Write a value to address 0x00, for example 0x0B
Then read the address 0x00 and determine whether the value is 0x0B
*/
eeprom_writebyte(0x00, test_byte1);
delay_ms(10);
eeprom_readbyte(0x00,&test_byte2);
assert_param( test_byte1== test_byte2 );
if( test_byte1 == test_byte2 )
{
printf( "Byte Read andByte Write Test Pass\r\n" );
}
/*
Step 2: Use address 0x08 as the starting address and write 8 bytes of data continuously
Then read 8 bytes from the starting address and compare the written and read bytes.
The condition for success is that the contents of the bytes written and read are the same
*/
uint8_t test_buf1[8]= {1,2,3,4,5,6,7,8};
uint8_t test_buf2[8]= {0,0,0,0,0,0,0,0};
eeprom_writepage(0x08, test_buf1, 8);
delay_ms(10);
eeprom_readpage(0x08, test_buf2, 8);
assert_param( memcmp( test_buf1, test_buf2,8) == 0 );
if(!memcmp(test_buf1, test_buf2,8))
{
printf("Page Read andPage Write Test Pass!\r\n");
}
#endif
}
6.2 Test Results
Previous article:How to achieve low power consumption under FreeRTOS - MSP430F5438 platform
Next article:CC2530 RF part use - to achieve point-to-point transmission and reception
Recommended ReadingLatest update time:2024-11-16 15:55
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- [RISC-V MCU CH32V103 Review] + Carbon Monoxide Alarm
- Talking about FPGA
- The temperature of the voltage regulator
- Father's Day is coming~
- 5G is here. How will it be applied in smart monitoring and smart home? What is the prospect of the weak current industry?
- Why can't the crystal oscillator be placed on the edge of the PCB? Explain with actual examples!
- Award-winning live broadcast: ADI's technology and product registration for China's energy Internet applications has begun~
- Speechless! There will be a noise bump in the spectrum when there is no signal input at low frequency. Can you experts see what's going on?
- AD ground line width setting
- Is this injury serious?