STM32 软件 I2C Source Files (No Clock Strech)
** 验证程序:**
const uint8_t ucPattern[8] = { 0x55, 0xAA, 0x66, 0xBB, 0x77, 0xCC, 0x88, 0xDD };
uint8_t ucBuf[8]= {0};
extern char stringbuf[];
/* Show Error Message */
void vDisplayErrorAndHold( uint16_t errcode)
{
switch( errcode )
{
case 0:
printf("\r\nIIC Write Error");
break;
case 1:
printf("\r\nIIC Read Error");
break;
case 2:
printf("\r\nIIC Compare Error");
break;
}
portBuzzerOn( );
while(1);
}
/* Test i2c devices */
void vTestI2CAccess(void)
{
for( uint16_t i=0; i<100; i++ )
{
/* Fill 256bytes */
for( uint16_t j=0; j< 32; j++ )
{
if( FAIL == SoftIICWrite( 0xA0, (uint8_t )(j*8), 8, ucPattern ) ) vDisplayErrorAndHold(0);
DelayXms(10);
sprintf( stringbuf, “Write Page: %3u”, j)
LCDPUTSTRING( 0, 0, stringbuf );
}
/* Read Data Back */
for( uint16_t j=0; j< 32; j++ )
{
if( FAIL == SoftIICRead( 0xA1, (uint8_t )(j*8), 8, ucBuf )) vDisplayErrorAndHold(1);
for(uint16_t k=0; k<8; k++) if( ucBuf[k] != ucPattern[k] ) vDisplayErrorAndHold(2);
sprintf( stringbuf, “Read Page: %3u”, j );
LCDPUTSTRING( 0, 1, stringbuf );
}
}
}
i2C Write
Write Bytes
I2C Read
Header File: (SoftIIC.h)
/****************************************************************************
* Software IIC Lib @ ARM M3
* Since STM32F103C8/C6 came-out IIC unstable issue, and C6 lacks I2C2.
* Porting software IIC for simultaneously switch between C8/C6 by request.
*
* Usage:
* 1. Modify SoftIIC.H to match hardware pin Configuration.
* Both SDA/SCL pin as Output_Open_Drain (OD) without pull-up/ pull-down.
*
* SoftIICRead(uint8_t Dev, uint8_t ucAddr, uint8_t ucLen, uint8_t* pBuf);
* Dev: slave device 8-bits address.
* ucAddr: Register address for access
* ucLen: Bytes
* pBuf: Data for buffer for store data.
*
* Example: ucI2CStaus = SoftIICRead( 0xA0, 0, 8, pBuf );
*
* SoftIICWrite(uint8_t Dev, uint8_t ucAddr, uint8_t ucLen, uint8_t* pBuf);
* Dev: slave device 8-bits address.
* ucAddr: Register address for access
* ucLen: Bytes
* pBuf: Data for buffer for store data.
*
* Example: ucI2CStaus = SoftIICWrite( 0xA0, 0, 8, pBuf );
*
* By Jason Lu. 2022/08/31 @WUXI
*/
#ifndef __SOFTIIC_H_
#define __SOFTIIC_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "brd.h"
extern void DelayXus(uint32_t );
typedef enum Acknowledge_Type { ACK=0x00U , NACK=!ACK } Acknowledge_TypeDef;
#define I2C_ERROR_NONE 0x00U /* No error */
#define I2C_ERROR_BERR 0x01U /* BERR error */
#define I2C_ERROR_AF 0x04U /* AF error */
#define I2C_ERROR_TIMEOUT 0x20U /* Timeout Error */
#define I2C_ERROR_BUSBUSY 0x80U /* BUS BUSY */
#if 0
// I2C1 Default Hardware Pin
#define hwSCL (1U << 6)
#define portSetSCL() GPIOB->BSRR = hwSCL
#define portResetSCL() GPIOB->BRR = hwSCL
#define portGetSCL() (0U != (GPIOB->IDR & hwSCL))
#define hwSDA ( 1U << 7 )
#define portSetSDA() GPIOB->BSRR = hwSDA
#define portResetSDA() GPIOB->BRR = hwSDA
#define portGetSDA() (0U != (GPIOB->IDR & hwSDA))
#else
// I2C2 Default Hardware Pin
#define hwSCL (1U << 10)
#define portSetSCL() GPIOB->BSRR = hwSCL
#define portResetSCL() GPIOB->BRR = hwSCL
#define portGetSCL() (0U != (GPIOB->IDR & hwSCL))
#define hwSDA ( 1U << 11 )
#define portSetSDA() GPIOB->BSRR = hwSDA
#define portResetSDA() GPIOB->BRR = hwSDA
#define portGetSDA() (0U != (GPIOB->IDR & hwSDA))
#endif
/* Both High as Bus Free */
#define IsBusFree() ( portGetSCL() && portGetSCL() )
/* Apply Acknowledge to SDA pin */
void IICAck(uint8_t bAck);
#define IIC_ACK() IICAck(0)
#define IIC_NACK() IICAck(1)
/* IIC Bus Start */
void IICStart(void);
/* IIC Bus Stop */
void IICStop(void) ;
/* Write 8-bits & Check Acknowledge */
uint8_t IICWrite8Bits( uint8_t );
/* Read 8-bits without Acknowledge */
void IICRead8Bits(unsigned char* );
/* Read Multiple Bytes */
uint8_t SoftIICRead(uint8_t Dev, uint8_t ucAddr, uint8_t ucLen, uint8_t* pBuf);
/* Write Multiple Bytes */
uint8_t SoftIICWrite(uint8_t Dev, uint8_t ucAddr, uint8_t ucLen, uint8_t* pBuf);
#ifdef __cplusplus
}
#endif
#endif
注意事项:
- Dummy for /while loop可能会在 gcc 优化时被移除, 造时序要注意, 优化后会太快 > 400KHz.
- ATMEL 24Cxx 的 Acknowledge 需要约 700ns才会响应, 要保留反应时间
- ATMEL 24Cxx 在写后需要一段写入时间, 旧数据 10ms, 不过这期间 SCL并无 Clock Strech现象(时序上可以明显看出), 可以继续操作其他 Device(s).
- 旧版本的 Read时序有问题, 修正:
void IICRead8Bits(uint8_t* pdata)
{
uint8_t i;
*pdata = 0;
for(i = 8; i > 0 ; i--)
{
DelayXus(3);
portSetSCL();
*pdata <<= 1;
if(portGetSDA())
{ *pdata +=1; }
DelayXus(3);
portResetSCL();
}
}
STM32 软件 I2C Source Files (No Clock Strech)
数据剪辑自原厂规格书, 版权归原所有人拥有。
档案取自互联网!如有侵权或不适用情形, 请联系移除!
** 使用有风险, 请详阅原厂使用说明!
** 范例码为自用,请勿引用, Ctrl-C, Ctrl-V结果自行承担!