一、stm32cudeMX的一些配置
这里配置i2c的模式和速率
二、代码实现
1、读取带寄存器地址
ErrorStatus I2C_Read(I2C_TypeDef *I2Cx , uint8_t SlaveAddr_IC, uint8_t addr_reg, uint8_t *pData, uint16_t Len, uint16_t Timeout)
{
uint8_t size;
uint16_t t_out = 0;
if((pData == NULL) || (Len == 0U)) //对数据为空和长度为0,作返回处理
{
return ERROR;
}
while(LL_I2C_IsActiveFlag_BUSY(I2Cx)==SET){
/* 确认是否使能 */
if(!LL_I2C_IsEnabled(I2Cx)){
LL_I2C_Enable(I2Cx);
}
/* 清除 RXNE 标志 */
if (LL_I2C_IsActiveFlag_RXNE(I2Cx)){
LL_I2C_ReceiveData8(I2Cx);
}
/* 结束传输 */
if(LL_I2C_IsActiveFlag_STOP(I2Cx)){
LL_I2C_ClearFlag_STOP(I2Cx);
}
/* 清除 NACKF 标志*/
if(LL_I2C_IsActiveFlag_NACK(I2Cx)){
LL_I2C_ClearFlag_NACK(I2Cx);
}
/* 超时报错*/
if(LL_SYSTICK_IsActiveCounterFlag()){
if (t_out++ == Timeout){
LL_I2C_ClearFlag_STOP(I2Cx);
return ERROR;
}
}
}
//设置设备地址
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC,LL_I2C_ADDRSLAVE_7BIT, 1,LL_I2C_MODE_SOFTEND,LL_I2C_GENERATE_START_WRITE);
// 等待上一次传输完成
while(LL_I2C_IsActiveFlag_TXE(I2Cx)==RESET);
//发送寄存器地址
LL_I2C_TransmitData8(I2Cx, addr_reg);
t_out=0;
while(LL_I2C_IsActiveFlag_TXE(I2Cx)==RESET){
if( t_out++ == Timeout ){//aproximate 150ms
LL_I2C_ClearFlag_TXE(I2Cx);
return ERROR;
}
}
while(LL_I2C_IsActiveFlag_TC(I2Cx)==RESET);
if(Len > 0xFF)
{
size = 0xFF;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_START_READ);
}
else
{
size = Len;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ);
}
t_out=0;
while(Len | (!LL_I2C_IsActiveFlag_STOP(I2Cx)))
{
if(LL_I2C_IsActiveFlag_RXNE(I2Cx)){
*pData = LL_I2C_ReceiveData8(I2Cx);
t_out=0;
pData++;
size--;
Len--;
}
if( t_out++ == Timeout ){//aproximate 150ms
LL_I2C_ClearFlag_STOP(I2Cx);
return ERROR;
}
if(Len != 0 && size == 0)
{
while(LL_I2C_IsActiveFlag_TCR(I2Cx) == RESET);
if(Len > 0xFF)
{
size = 0xFF;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_NOSTARTSTOP);
}
else
{
size = Len;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_NOSTARTSTOP);
}
}
}
while(LL_I2C_IsActiveFlag_STOP(I2Cx) == RESET);
/* 清除标志位 */
LL_I2C_ClearFlag_STOP(I2Cx);
return SUCCESS;
}
2、读取不带寄存器地址
ErrorStatus I2C_Read_Without_Reg_Addr(I2C_TypeDef *I2Cx , uint8_t SlaveAddr_IC, uint8_t *pData, uint16_t Len, uint16_t Timeout)
{
uint8_t size;
uint16_t t_out = 0;
if((pData == NULL) || (Len == 0U))
{
return ERROR;
}
while(LL_I2C_IsActiveFlag_BUSY(I2Cx)==SET){
/* 确认是否使能 */
if(!LL_I2C_IsEnabled(I2Cx)){
LL_I2C_Enable(I2Cx);
}
/* clear RXNE flag */
if (LL_I2C_IsActiveFlag_RXNE(I2Cx)){
LL_I2C_ReceiveData8(I2Cx);
}
/* End of Transfer */
if(LL_I2C_IsActiveFlag_STOP(I2Cx)){
LL_I2C_ClearFlag_STOP(I2Cx);
}
/* Clear NACKF Flag */
if(LL_I2C_IsActiveFlag_NACK(I2Cx)){
LL_I2C_ClearFlag_NACK(I2Cx);
}
if(LL_SYSTICK_IsActiveCounterFlag()){
if (t_out++ == Timeout){
LL_I2C_ClearFlag_STOP(I2Cx);
return ERROR;
}
}
}
if(Len > 0xFF)
{
size = 0xFF;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_START_READ);
}
else
{
size = Len;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ);
}
t_out=0;
while(Len | (!LL_I2C_IsActiveFlag_STOP(I2Cx)))
{
if(LL_I2C_IsActiveFlag_RXNE(I2Cx)){
*pData = LL_I2C_ReceiveData8(I2Cx);
t_out=0;
pData++;
size--;
Len--;
}
if( t_out++ == Timeout ){//aproximate 150ms
LL_I2C_ClearFlag_STOP(I2Cx);
return ERROR;
}
if(Len != 0 && size == 0)
{
while(LL_I2C_IsActiveFlag_TCR(I2Cx) == RESET);
if(Len > 0xFF)
{
size = 0xFF;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_NOSTARTSTOP);
}
else
{
size = Len;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_NOSTARTSTOP);
}
}
}
while(LL_I2C_IsActiveFlag_STOP(I2Cx) == RESET);
/* 清除标志位 */
LL_I2C_ClearFlag_STOP(I2Cx);
return SUCCESS;
}
3、写入带寄存器地址
ErrorStatus I2C_Write(I2C_TypeDef *I2Cx , uint8_t SlaveAddr_IC, uint8_t addr_reg, uint8_t *pData, uint16_t Len, uint16_t Timeout)
{
uint8_t size;
if((pData == NULL) || (Len == 0U))
{
return ERROR;
}
while(LL_I2C_IsActiveFlag_BUSY(I2Cx)==SET){
/* 确认是否使能 */
if(!LL_I2C_IsEnabled(I2Cx)){
LL_I2C_Enable(I2Cx);
}
/* clear RXNE flag */
if (LL_I2C_IsActiveFlag_RXNE(I2Cx)){
LL_I2C_ReceiveData8(I2Cx);
}
/* End of Transfer */
if(LL_I2C_IsActiveFlag_STOP(I2Cx)){
LL_I2C_ClearFlag_STOP(I2Cx);
}
/* Clear NACKF Flag */
if(LL_I2C_IsActiveFlag_NACK(I2Cx)){
LL_I2C_ClearFlag_NACK(I2Cx);
}
if(LL_SYSTICK_IsActiveCounterFlag()){
if (Timeout-- == 0){
LL_I2C_ClearFlag_STOP(I2Cx);
return ERROR;
}
}
}
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, 1, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_START_WRITE);
while(LL_I2C_IsActiveFlag_TXIS(I2Cx) == RESET);
LL_I2C_TransmitData8(I2Cx, addr_reg);/**< reg_addr目前只支持单字节地址 */
while(LL_I2C_IsActiveFlag_TCR(I2Cx) == RESET);
if(Len > 0xFF)
{
size = 0xFF;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_NOSTARTSTOP);
}
else
{
size = Len;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_NOSTARTSTOP);
}
while(Len)
{
while(LL_I2C_IsActiveFlag_TXIS(I2Cx) == RESET){}
LL_I2C_TransmitData8(I2Cx, *pData);
pData++;
size--;
Len--;
if(Len != 0 && size == 0)
{
while(LL_I2C_IsActiveFlag_TCR(I2Cx) == RESET);
if(Len > 0xFF)
{
size = 0xFF;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_NOSTARTSTOP);
}
else
{
size = Len;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_NOSTARTSTOP);
}
}
}
while(LL_I2C_IsActiveFlag_STOP(I2Cx)==RESET){
if(LL_SYSTICK_IsActiveCounterFlag()){
if (Timeout-- == 0){
LL_I2C_ClearFlag_STOP(I2Cx);
return ERROR;
}
}
}
/* 清除标志位 */
LL_I2C_ClearFlag_STOP(I2Cx);
return SUCCESS;
}
4、写入不带寄存器地址
ErrorStatus I2C_Write_Without_Reg_Addr(I2C_TypeDef *I2Cx , uint8_t SlaveAddr_IC, uint8_t *pData, uint16_t Len, uint16_t Timeout)
{
uint8_t size;
if((pData == NULL) || (Len == 0U))
{
return ERROR;
}
while(LL_I2C_IsActiveFlag_BUSY(I2Cx)==SET){
/* 确认是否使能 */
if(!LL_I2C_IsEnabled(I2Cx)){
LL_I2C_Enable(I2Cx);
}
/* clear RXNE flag */
if (LL_I2C_IsActiveFlag_RXNE(I2Cx)){
LL_I2C_ReceiveData8(I2Cx);
}
/* End of Transfer */
if(LL_I2C_IsActiveFlag_STOP(I2Cx)){
LL_I2C_ClearFlag_STOP(I2Cx);
}
/* Clear NACKF Flag */
if(LL_I2C_IsActiveFlag_NACK(I2Cx)){
LL_I2C_ClearFlag_NACK(I2Cx);
}
if(LL_SYSTICK_IsActiveCounterFlag()){
if (Timeout-- == 0){
LL_I2C_ClearFlag_STOP(I2Cx);
return ERROR;
}
}
}
if(Len > 0xFF)
{
size = 0xFF;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_NOSTARTSTOP);
}
else
{
size = Len;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_NOSTARTSTOP);
}
while(Len)
{
while(LL_I2C_IsActiveFlag_TXIS(I2Cx) == RESET){}
LL_I2C_TransmitData8(I2Cx, *pData);
pData++;
size--;
Len--;
if(Len != 0 && size == 0)
{
while(LL_I2C_IsActiveFlag_TCR(I2Cx) == RESET);
if(Len > 0xFF)
{
size = 0xFF;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_NOSTARTSTOP);
}
else
{
size = Len;
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, size, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_NOSTARTSTOP);
}
}
}
while(LL_I2C_IsActiveFlag_STOP(I2Cx)==RESET){
if(LL_SYSTICK_IsActiveCounterFlag()){
if (Timeout-- == 0){
LL_I2C_ClearFlag_STOP(I2Cx);
return ERROR;
}
}
}
/* 清除标志位 */
LL_I2C_ClearFlag_STOP(I2Cx);
return SUCCESS;
}
带不带寄存器地址的区别主要是有没有下面这两段代码,有的芯片不需要寄存器地址,根据数据来做反馈。LL_I2C_MODE_SOFTEND用于读,LL_I2C_MODE_RELOAD和LL_I2C_MODE_AUTOEND用于写。
读
//设置设备地址
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC,LL_I2C_ADDRSLAVE_7BIT, 1,LL_I2C_MODE_SOFTEND,LL_I2C_GENERATE_START_WRITE);
// 等待上一次传输完成
while(LL_I2C_IsActiveFlag_TXE(I2Cx)==RESET);
//发送寄存器地址
LL_I2C_TransmitData8(I2Cx, addr_reg);
写
LL_I2C_HandleTransfer(I2Cx, SlaveAddr_IC, LL_I2C_ADDRSLAVE_7BIT, 1, LL_I2C_MODE_RELOAD, LL_I2C_GENERATE_START_WRITE);
while(LL_I2C_IsActiveFlag_TXIS(I2Cx) == RESET);
LL_I2C_TransmitData8(I2Cx, addr_reg);/**< reg_addr目前只支持单字节地址 */
while(LL_I2C_IsActiveFlag_TCR(I2Cx) == RESET);
4个函数返回为一个枚举
typedef enum
{
SUCCESS = 0,
ERROR = !SUCCESS
} ErrorStatus;
三、总结
在stm32g030F6p6上用的没问题。