stm32硬體I2C測試例程,親測可用
阿新 • • 發佈:2019-02-18
對於stm32的硬體I2C確實有不盡人意的地方。但是還是可以實現的,畢竟使用stm32的硬體I2C確實比使用IO口來模擬簡單的多。下面的程式程式碼是使用stm32F03ZET6的I2C1(PB6,PB7)和AT24C02的EEPROM來測試的。希望對於需要的朋友有幫助。
i2c.c
#include "iic.h" #include "stm32f10x.h" #include "usart.h" u16 timeout=TIMEOUT; /*i2c的初始化*/ void IIC1_Init() { GPIO_InitTypeDef GPIO_InitStruct; I2C_InitTypeDef I2C_InitStruct; RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //GPIO的配置 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_OD; GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7; GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStruct); //IIC的配置 I2C_InitStruct.I2C_Ack=I2C_Ack_Enable; I2C_InitStruct.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit; I2C_InitStruct.I2C_ClockSpeed=10000; I2C_InitStruct.I2C_DutyCycle=I2C_DutyCycle_2; I2C_InitStruct.I2C_Mode=I2C_Mode_I2C; I2C_InitStruct.I2C_OwnAddress1=0x55; I2C_Init(I2C1,&I2C_InitStruct); I2C_Cmd(I2C1,ENABLE); } /*寫入一個位元組*/ void IIC_WriteByte(u8 addr,u8 data) { I2C_EE_WaitEepromStandbyState(); I2C_GenerateSTART(I2C1,ENABLE);//傳送起始訊號 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT))//檢測 EV5事件 { if((timeout--)==0) printf("EV5 Fail"); } timeout=1000; I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Transmitter);//傳送7位EEPROM的硬體地址 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))//檢測EV6事件 { if((timeout--)==0) printf("EV6 Fail"); } timeout=1000; I2C_SendData(I2C1,addr);//傳送操作的記憶體地址 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED))//檢測EV8事件 { if((timeout--)==0) printf("EV8 Fail"); } timeout=1000; I2C_SendData(I2C1,data);//要寫入的資料(一個位元組) while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED))//檢測EV8事件 { if((timeout--)==0) printf("EV8 Fail"); } timeout=1000; I2C_GenerateSTOP(I2C1,ENABLE);//傳送結束訊號 } /*讀取一個位元組*/ u8 IIC_ReadByte(u8 addr) { u8 readtemp; I2C_EE_WaitEepromStandbyState();//等待EEPROM釋放匯流排 I2C_GenerateSTART(I2C1,ENABLE); while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT))//5 { if((timeout--)==0) printf("EV5 Fail"); } timeout=1000; I2C_Send7bitAddress(I2C1,0xA1,I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))//6 { if((timeout--)==0) printf("EV6 Fail"); } timeout=1000; I2C_SendData(I2C1,addr); while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS ) { if((timeout--)==0) printf("EV8 Fail"); } timeout=1000; I2C_GenerateSTART(I2C1,ENABLE); while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)) { if((timeout--)==0) printf("EV5 Fail"); } timeout=1000; I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Receiver); while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) { if((timeout--)==0) printf("EV6 Fail"); } timeout=1000; I2C_AcknowledgeConfig(I2C1,DISABLE); /* 檢測 EV7 事件 */ while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS ) { if((timeout--)==0) printf("EV7 Fail"); } timeout=1000; /* 讀取接收資料 */ readtemp = I2C_ReceiveData(I2C1); /* 停止訊號 */ I2C_GenerateSTOP(I2C1,ENABLE); return readtemp; } /*等待eeprom釋放匯流排*/ void I2C_EE_WaitEepromStandbyState(void) { do { I2C_GenerateSTART(I2C1, ENABLE); while(I2C_GetFlagStatus(I2C1,I2C_FLAG_SB)==ERROR);//檢測EV5事件 I2C_Send7bitAddress(I2C1,0xA1,I2C_Direction_Transmitter); }while(I2C_GetFlagStatus(I2C1,I2C_FLAG_ADDR)==ERROR);// I2C_ClearFlag(I2C1, I2C_FLAG_AF);//清楚標誌位 I2C_GenerateSTOP(I2C1, ENABLE); //結束訊號 } /* 向eeprom中寫入n個數據*/ void I2C_WriteNumData(u8 addr,u8 *str, u8 numToWrite) { if((addr+numToWrite)>255)//避免寫入的資料超過總的記憶體 { printf("refuse to write\n"); printf("please enter less than %d char\n",(255-addr)); } else { printf("allow to write\n"); while(numToWrite) { IIC_WriteByte(addr,*str); addr++; str++; numToWrite--; } printf("write success\n"); } } void I2C_ReadNumData(u8 addr,u8 *str,u8 numToRead) { while(numToRead) { *str=IIC_ReadByte(addr); addr++; str++; numToRead--; } }
usart.c
#include "usart.h" #include "stm32f10x.h" void USART1_Init() { GPIO_InitTypeDef GPIO_InitStruct; USART_InitTypeDef USART_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE); GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9; GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStruct); GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING; GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10; GPIO_Init(GPIOA,&GPIO_InitStruct); USART_InitStruct.USART_BaudRate=115200; USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None; USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx; USART_InitStruct.USART_Parity=USART_Parity_No; USART_InitStruct.USART_StopBits=USART_StopBits_1; USART_InitStruct.USART_WordLength=USART_WordLength_8b; USART_Init(USART1,&USART_InitStruct); USART_Cmd(USART1,ENABLE); } void USART1_SendByte(u8 data) { USART_SendData(USART1,data); while(!USART_GetFlagStatus(USART1,USART_FLAG_TXE)); } void USART1_SendStr(u8 *str) { unsigned int i=0; for(i=0;*str!='\0';i++) { USART1_SendByte(*str); str++; } while(!USART_GetFlagStatus(USART1,USART_FLAG_TC)); } int fputc(int ch, FILE *f) { /* 傳送一個位元組資料到串列埠 */ USART_SendData(USART1, (uint8_t) ch); /* 等待發送完畢 */ while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); return (ch); }
main.c
#include "stm32f10x.h" #include "usart.h" #include "iic.h" #include <stdio.h> int main() { u8 a[10]={9,8,7,6,5,4,3,2,1,0}; u8 b[10]={0}; u8 i=0; USART1_Init(); IIC1_Init(); I2C_WriteNumData(125,a,10); I2C_ReadNumData(125,b,10); for(i=0;i<10;i++) { printf("%d\t",b[i]); } }