This article uses software-simulated I2C to implement a function library for operating 24LC16B on the STM8L15x series chips.
Header file definition:
#ifndef _24LC16B_H
#define _24LC16B_H
#include "Hal_I2CSoft.h"
#define MAXROM_24LC16B (2048)
extern void Hal24LC16BInit(I2CSoftConfig_t* i2cCfg);
extern u8 Hal24LC16B_ReadByte(u16 addr);
extern void Hal24LC16B_WriteByte(u16 addr, u8 data);
extern void Hal24LC16B_ReadBuf(u16 addr, u8 *buf, u16 len);
extern void Hal24LC16B_WriteBuf(u16 addr, u8 *buf, u16 len);
extern void Hal24L68B_WritePage(u16 addr, u8 *buf);
#endif
Specific operation function:
/**
******************************************************************************
* @f file 24LC16B.c
* @Author huangqi
* @Version V1.0.0
* @Date 2014-12-20
* @Description Microchip's 24LC16B operation function library
******************************************************************************
*/
#include "Hal_I2CSoft.h"
#include "24LC16B.h"
I2CSoftConfig_t *i2cCfg;
/********************************************************************************
* @Function name Hal24LC16BInit
*
* @Function Initialize 24LC16B
*
* @parameter i2cCfg: I2CSoft port information
*
* @return value None
*********************************************************************************/
void Hal24LC16BInit(I2CSoftConfig_t* i2cPortConfig)
{
i2cCfg = i2cPortConfig;
I2CSoft_Init(i2cCfg);
}
/********************************************************************************
* @Function name Hal24LC16B_ReadByte
*
* @Function Read a byte from 24LC16B
*
* @param addr: address
*
* @return value The bytes read
*********************************************************************************/
u8 Hal24LC16B_ReadByte(u16 addr)
{
u8 tmp = 0;
do
{
I2CSoft_Start(i2cCfg);
I2CSoft_SendByte(i2cCfg, 0xA0+((addr/256)<<1));//write command
}
while(I2CSoft_WaitAck(i2cCfg));
I2CSoft_SendByte(i2cCfg, addr%256);
I2CSoft_WaitAck(i2cCfg);
I2CSoft_Start(i2cCfg);
I2CSoft_SendByte(i2cCfg, 0xA0+((addr/256)<<1)+1); //write command
I2CSoft_WaitAck(i2cCfg);
tmp = I2CSoft_RecvByte(i2cCfg,0);
I2CSoft_Stop(i2cCfg);
return tmp;
}
/********************************************************************************
* @Function name Hal24LC16B_WriteByte
*
* @Function Write a byte to 24LC16B
*
* @param addr: address
* data: data to be written
*
* @return value None
*********************************************************************************/
void Hal24LC16B_WriteByte(u16 addr, u8 data)
{
do
{
I2CSoft_Start(i2cCfg);
I2CSoft_SendByte(i2cCfg, 0xA0+((addr/256)<<1));//write command
}
while(I2CSoft_WaitAck(i2cCfg));
I2CSoft_SendByte(i2cCfg, addr%256);
I2CSoft_WaitAck(i2cCfg);
I2CSoft_SendByte(i2cCfg, data); //write command
I2CSoft_WaitAck(i2cCfg);
I2CSoft_Stop(i2cCfg);
//delay_us(3000);//Must wait for EEPROM writing to complete
}
/********************************************************************************
* @Function name Hal24LC16B_WriteByte
*
* @Function Write a page to 24LC16B (16Byte in total)
*
* @param addr: address
* data: data to be written
*
* @return value None
*********************************************************************************/
void Hal24L68B_WritePage(u16 addr, u8 *buf)
{
u8 cnt=16;
if((addr+16)%256<16)
return;
do
{
I2CSoft_Start(i2cCfg);
I2CSoft_SendByte(i2cCfg, 0xA0+((addr/256)<<1));//write command
}
while(I2CSoft_WaitAck(i2cCfg));
I2CSoft_SendByte(i2cCfg, addr%256);
I2CSoft_WaitAck(i2cCfg);
while(cnt--)
{
I2CSoft_SendByte(i2cCfg, *buf++); //write command
I2CSoft_WaitAck(i2cCfg);
}
I2CSoft_Stop(i2cCfg);
//delay_us(3000);//Must wait for EEPROM writing to complete
}
/********************************************************************************
* @Function name Hal24LC16B_ReadBuf
*
* @Function Read data from 24LC16B
*
* @param addr: address
* buf: read data
* len: the length of the data to be read
*
* @return value None
*********************************************************************************/
void Hal24LC16B_ReadBuf(u16 addr, u8 *buf, u16 len)
{
u16 i = 0;
if((len>0)&&(addr+len)>=(MAXROM_24LC16B-1))
return;
do
{
I2CSoft_Start(i2cCfg);
I2CSoft_SendByte(i2cCfg, 0xA0+((addr/256)<<1));//write command
}
while(I2CSoft_WaitAck(i2cCfg));
I2CSoft_SendByte(i2cCfg, addr%256);
I2CSoft_WaitAck(i2cCfg);
I2CSoft_Start(i2cCfg);
I2CSoft_SendByte(i2cCfg, 0xA0+((addr/256)<<1)+1); //write command
I2CSoft_WaitAck(i2cCfg);
for(i = 0; i *buf++ = I2CSoft_RecvByte(i2cCfg,1); } *buf = I2CSoft_RecvByte(i2cCfg,0); I2CSoft_Stop(i2cCfg); } /******************************************************************************** * @Function name Hal24LC16B_WriteBuf * * @Function Write data to 24LC16B * * @param addr: address * buf: data to be written * len: length of the data to be written * * @return value None *********************************************************************************/ void Hal24LC16B_WriteBuf(u16 addr, u8* buf, u16 len) { u16 i; if((len>0)&&(addr+len)>=(MAXROM_24LC16B-1)) return; for(i=0; i Hal24LC16B_WriteByte(addr++,*buf++); } } I2C software simulation driver: head File: #ifndef _HAL_I2CSOFT_H #define _HAL_I2CSOFT_H #include "stm8l15x.h" typedef struct I2CSoftConfig_t { GPIO_TypeDef* SCL_Port; GPIO_Pin_TypeDef SCL_Pin; GPIO_TypeDef* SDA_Port; GPIO_Pin_TypeDef SDA_Pin; }I2CSoftConfig_t; //extern void delay_us(u16 time); extern void I2CSoft_Init(I2CSoftConfig_t* i2cConfg); extern void I2CSoft_Start(I2CSoftConfig_t *i2cPortConfig); extern void I2CSoft_Stop(I2CSoftConfig_t *i2cPortConfig); extern u8 I2CSoft_WaitAck(I2CSoftConfig_t *i2cPortConfig); extern void I2CSoft_SendByte(I2CSoftConfig_t *i2cPortConfig, u8 sendByte); extern u8 I2CSoft_RecvByte(I2CSoftConfig_t *i2cPortConfig, u8 ack); #endif I2C protocol implementation: /** ****************************************************************************** * @f file hal_Flash.c * @Author huangqi * @Version V1.0.0 * @Date 2014-12-23 * @description Simulate I2C related operations ****************************************************************************** */ #include "Hal_I2CSoft.h" void delay_us(u32 us) { for( u32 x=us;x>0;x-- ) { nop();nop();nop();nop(); } } void I2CSoft_Init(I2CSoftConfig_t* i2cPortConfig) { GPIO_Init(i2cPortConfig->SCL_Port,i2cPortConfig->SCL_Pin,GPIO_Mode_Out_PP_Low_Slow);//GPIO_Mode_Out_OD_Low_Slow); GPIO_Init(i2cPortConfig->SDA_Port,i2cPortConfig->SDA_Pin,GPIO_Mode_Out_OD_Low_Slow);//GPIO_Mode_Out_OD_Low_Slow); } void I2CSoft_Start(I2CSoftConfig_t* i2cPortConfig) { // i2cPortConfig->SDA_Port->DDR |= i2cPortConfig->SDA_Pin; i2cPortConfig->SDA_Port->ODR |= i2cPortConfig->SDA_Pin; i2cPortConfig->SCL_Port->ODR |= i2cPortConfig->SCL_Pin; delay_us(2); i2cPortConfig->SDA_Port->ODR &= ~i2cPortConfig->SDA_Pin; delay_us(2); i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; } void I2CSoft_Stop(I2CSoftConfig_t* i2cPortConfig) { i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; // i2cPortConfig->SDA_Port->DDR |= i2cPortConfig->SDA_Pin; i2cPortConfig->SDA_Port->ODR &= ~i2cPortConfig->SDA_Pin; delay_us(2); i2cPortConfig->SCL_Port->ODR |= i2cPortConfig->SCL_Pin; i2cPortConfig->SDA_Port->ODR |= i2cPortConfig->SDA_Pin; delay_us(2); } u8 I2CSoft_WaitAck(I2CSoftConfig_t* i2cPortConfig) { u8 ucErrTime; // i2cPortConfig->SDA_Port->DDR &= ~i2cPortConfig->SDA_Pin; i2cPortConfig->SDA_Port->ODR |= i2cPortConfig->SDA_Pin; //Open-drain output turns off NMOS and uses it as input //delay_us(2); i2cPortConfig->SCL_Port->ODR |= i2cPortConfig->SCL_Pin; delay_us(2); while(i2cPortConfig->SDA_Port->IDR & i2cPortConfig->SDA_Pin) { ucErrTime++; if(ucErrTime>250) { I2CSoft_Stop(i2cPortConfig); return 1; } } i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; //delay_us(2); return 0; } static void I2CSoft_Ack(I2CSoftConfig_t* i2cPortConfig) { i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; //i2cPortConfig->SDA_Port->DDR |= i2cPortConfig->SDA_Pin; i2cPortConfig->SDA_Port->ODR &= ~i2cPortConfig->SDA_Pin; delay_us(2); i2cPortConfig->SCL_Port->ODR |= i2cPortConfig->SCL_Pin; delay_us(2); i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; } static void I2CSoft_NoAck(I2CSoftConfig_t* i2cPortConfig) { i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; // i2cPortConfig->SDA_Port->DDR |= i2cPortConfig->SDA_Pin; i2cPortConfig->SDA_Port->ODR |= i2cPortConfig->SDA_Pin; delay_us(2); i2cPortConfig->SCL_Port->ODR |= i2cPortConfig->SCL_Pin; delay_us(2); i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; } void I2CSoft_SendByte(I2CSoftConfig_t* i2cPortConfig, u8 sendByte) { u8 i=8; // i2cPortConfig->SDA_Port->DDR |= i2cPortConfig->SDA_Pin; i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; delay_us(2); while(i--) { if(sendByte&(1< { i2cPortConfig->SDA_Port->ODR |= i2cPortConfig->SDA_Pin; } else { i2cPortConfig->SDA_Port->ODR &= ~i2cPortConfig->SDA_Pin; } delay_us(2); i2cPortConfig->SCL_Port->ODR |= i2cPortConfig->SCL_Pin; delay_us(2); i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; } delay_us(2); // return I2C_RecvACK(); } //Read 1 byte, when ack=1, send ACK, when ack=0, send nACK u8 I2CSoft_RecvByte(I2CSoftConfig_t* i2cPortConfig, u8 ack) { u8 i=8,recvByte=0; i2cPortConfig->SDA_Port->ODR |= i2cPortConfig->SDA_Pin; //SDA is set as input // i2cPortConfig->SDA_Port->DDR &= ~i2cPortConfig->SDA_Pin; while(i--) { i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; delay_us(2); i2cPortConfig->SCL_Port->ODR |= i2cPortConfig->SCL_Pin;
Previous article:STM8L LCD interface detailed explanation and driver
Next article:STM8 tool IAR--debugging
Recommended ReadingLatest update time:2024-11-16 07:37
- Popular Resources
- Popular amplifiers
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
- How to choose between DT4215 and 15B for multimeter selection
- The world's first single-chip microcomputer was produced by TI
- EEWORLD University ---- Digital Integrated Circuit Analysis and Design
- The contradiction between insulation withstand voltage and ESD
- Buck Circuit
- High pass filter gain problem
- Using FPGA to realize accurate time keeping when GPS is out of step
- Bluetooth learning notes: analysis of example broadcast data
- Questions about DDR3 VTT
- EEWORLD University Hall----Live Replay: Keysight High-Speed Bus PCIe5.0 Technology Development and Test Sharing