如果是使用硬件IIC,这里使用的是STM32的固件库,硬件模块使用之前必须配置其参数,IIC的配置如下:
void IIC_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
IIC_InitTypeDef IIC_InitStructure;
RCC_ClocksTypeDef rcc_clocks;
/* GPIO Peripheral clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_IIC1|RCC_APB1Periph_IIC2|RCC_APB1Periph_IIC3, ENABLE);
/* Reset IICx IP */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_IIC1|RCC_APB1Periph_IIC2|RCC_APB1Periph_IIC3, ENABLE);
/* Release reset signal of IICx IP */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_IIC1|RCC_APB1Periph_IIC2|RCC_APB1Periph_IIC3, DISABLE);
/*IIC1 configuration*/
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_IIC1); //注意,此处不能合并写成GPIO_PinSource6|GPIO_PinSource7
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_IIC1);
//PB6: IIC1_SCL PB7: IIC1_SDA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* IIC Struct Initialize */
IIC_DeInit(IIC1);
IIC_InitStructure.IIC_Mode = IIC_Mode_IIC;
IIC_InitStructure.IIC_DutyCycle = IIC_DutyCycle_2;
IIC_InitStructure.IIC_OwnAddress1 = 0x00;
IIC_InitStructure.IIC_Ack = IIC_Ack_Enable;
IIC_InitStructure.IIC_ClockSpeed = 100000;
IIC_InitStructure.IIC_AcknowledgedAddress = IIC_AcknowledgedAddress_7bit;
IIC_Init(IIC1, &IIC_InitStructure);
/* IIC Initialize */
IIC_Cmd(IIC1, ENABLE);
/*IIC2 configuration*/
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_IIC2); //注意,此处不能合并写成GPIO_PinSource6|GPIO_PinSource7
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_IIC2);
//PB10: IIC2_SCL PB11: IIC2_SDA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* IIC Struct Initialize */
IIC_DeInit(IIC2);
IIC_InitStructure.IIC_Mode = IIC_Mode_IIC;
IIC_InitStructure.IIC_DutyCycle = IIC_DutyCycle_2;
IIC_InitStructure.IIC_OwnAddress1 = 0x00;
IIC_InitStructure.IIC_Ack = IIC_Ack_Enable;
IIC_InitStructure.IIC_ClockSpeed = 100000;
IIC_InitStructure.IIC_AcknowledgedAddress = IIC_AcknowledgedAddress_7bit;
IIC_Init(IIC2, &IIC_InitStructure);
/* IIC Initialize */
IIC_Cmd(IIC2, ENABLE);
/*IIC3 configuration*/
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_IIC3);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_IIC3);
//PA8: IIC3_SCL
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//PC9: IIC3_SDA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* IIC Struct Initialize */
IIC_DeInit(IIC3);
IIC_InitStructure.IIC_Mode = IIC_Mode_IIC;
IIC_InitStructure.IIC_DutyCycle = IIC_DutyCycle_2;
IIC_InitStructure.IIC_OwnAddress1 = 0x00;
IIC_InitStructure.IIC_Ack = IIC_Ack_Enable;
IIC_InitStructure.IIC_ClockSpeed = 100000;
IIC_InitStructure.IIC_AcknowledgedAddress = IIC_AcknowledgedAddress_7bit;
IIC_Init(IIC3, &IIC_InitStructure);
/* IIC Initialize */
IIC_Cmd(IIC3, ENABLE);
/*超时设置*/
RCC_GetClocksFreq(&rcc_clocks);
ulTimeOut_Time = (rcc_clocks.SYSCLK_Frequency /10000);
}
注意,IIC一定要加上超时的设置,否则当IIC总线出错时,没有超时检测可能造成MCU卡死在这里。
STM32F407的硬件IIC读一个字节与STM32F103类似,代码如下:
unsigned char IIC_Err=0;
uint8_t IIC_ReadOneByte(IIC_TypeDef *IICx,uint8_t IIC_Addr,uint8_t Reg_addr)
{
uint8_t readout;
u32 tmr;
tmr = ulTimeOut_Time;
while((--tmr)&&IIC_GetFlagStatus(IICx, IIC_FLAG_BUSY));
if(tmr==0) IIC_Err = 1;
IIC_GenerateSTART(IICx, ENABLE);
//发送IIC的START信号,接口自动从从设备编程主设备
tmr = ulTimeOut_Time;
while((--tmr)&&(!IIC_CheckEvent(IICx, IIC_EVENT_MASTER_MODE_SELECT)));
if(tmr==0) IIC_Err = 1;
IIC_Send7bitAddress(IICx,IIC_Addr,IIC_Direction_Transmitter);
tmr = ulTimeOut_Time;
while((--tmr)&&(!IIC_CheckEvent(IICx,IIC_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)));
if(tmr==0) IIC_Err = 1;
IIC_SendData(IICx, Reg_addr);
tmr = ulTimeOut_Time;
while((--tmr)&&(!IIC_CheckEvent(IICx,IIC_EVENT_MASTER_BYTE_TRANSMITTED)));
if(tmr==0) IIC_Err = 1;
IIC_GenerateSTART(IICx, ENABLE);
tmr = ulTimeOut_Time;
while((--tmr)&&(!IIC_CheckEvent(IICx, IIC_EVENT_MASTER_MODE_SELECT)));
if(tmr==0) IIC_Err = 1;
IIC_Send7bitAddress(IICx, IIC_Addr, IIC_Direction_Receiver);
tmr = ulTimeOut_Time;
while((--tmr)&&(!IIC_CheckEvent(IICx,
IIC_EVENT_MASTER_RECEIVER_MODE_SELECTED)));
if(tmr==0) IIC_Err = 1;
IIC_AcknowledgeConfig(IICx, DISABLE);
IIC_GenerateSTOP(IICx, ENABLE);
tmr = ulTimeOut_Time;
while((--tmr)&&(!(IIC_CheckEvent(IICx, IIC_EVENT_MASTER_BYTE_RECEIVED)))); /* EV7 */
if(tmr==0) IIC_Err = 1;
readout = IIC_ReceiveData(IICx);
IIC_AcknowledgeConfig(IICx, ENABLE);
return readout;
}
IIC_ReadOneByte函数输入参数有3个,分别是:IICx,表示使用的IIC编号,IIC_addr,表示从设备的IIC地址,reg_addr,表示要读取的从设备寄存器地址。IIC_ReadOneByte的返回值就是IIC总线上读取到的数据。读IIC数据后需要检查IIC_Err是否为0,若为0,表示读取IIC数据时出错(超时),读到的数据可能不正确。
向从设备写入一个字节的数据,代码如下:
unsigned char IIC_Err=0;
void IIC_WriteOneByte(IIC_TypeDef *IICx,uint8_t IIC_Addr,uint8_t
Reg_addr,uint8_t value)
{
u32 tmr;
tmr = ulTimeOut_Time;
while(IIC_GetFlagStatus(IICx, IIC_FLAG_BUSY));
while((--tmr)&&IIC_GetFlagStatus(IICx, IIC_FLAG_BUSY));
if(tmr==0) IIC_Err = 1;
IIC_GenerateSTART(IICx, ENABLE);
tmr = ulTimeOut_Time;
while((--tmr)&&(!IIC_CheckEvent(IICx, IIC_EVENT_MASTER_MODE_SELECT)));
if(tmr==0) IIC_Err = 1;
IIC_Send7bitAddress(IICx, IIC_Addr, IIC_Direction_Transmitter);
tmr = ulTimeOut_Time;
while((--tmr)&&(!IIC_CheckEvent(IICx,
IIC_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)));
if(tmr==0) IIC_Err = 1;
IIC_SendData(IICx, Reg_addr);
tmr = ulTimeOut_Time;
while((--tmr)&&(!IIC_CheckEvent(IICx, IIC_EVENT_MASTER_BYTE_TRANSMITTED)));
if(tmr==0) IIC_Err = 1;
IIC_SendData(IICx, value);
tmr = ulTimeOut_Time;
while((--tmr)&&(!IIC_CheckEvent(IICx, IIC_EVENT_MASTER_BYTE_TRANSMITTED)));
if(tmr==0) IIC_Err = 1;
IIC_GenerateSTOP(IICx, ENABLE);
//IIC_AcknowledgeConfig(IICx, DISABLE);
}
写IIC函数比读仅多了一个输入参数,即要写入的数据。同理,在函数执行完成后,需要检查IIC_Err是否为0以判断IIC是否出错。
有了读1个字节和写入1个字节的函数,当需要一次性读或写多个数据时,可以在上述函数的基础上扩展多字节操作。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- 69lv.com 版权所有 湘ICP备2023021910号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务