STM32标准库通用软件模拟IIC
继上次通用可移植的矩阵键盘之后,便继续寻找着下一个能够拿来只需改改引脚就可以使用的通用方案。
恰好最近在研究PCA9685,这是一片能够产生最多十六路PWM信号的芯片,通过IIC总线接口控制,只需要SCL+SDA,外加一根GND,就可以控制多达16路舵机,这属实减少了开发难度。也正是因此,博主产生了写一下通用IIC总线的想法,以下是代码
具体IIC时序在网上一搜一大把,这里就不再多说了。
博主使用的是STM32F103ZET6开发板测试,测试有效,引脚输出速度可以根据你的板子再做修改。
#ifndef _IIC_H
#define _IIC_H
#include "stm32f10x.h"
#include "delay.h"
// 只需要修改下方需要使用的端口,以及时钟即可,注意一定要全部修改好,
#define SCLPort GPIOE //SCL引脚端口
#define SCLPin GPIO_Pin_15 //SCL引脚
#define SCLPinCLK RCC_APB2Periph_GPIOE
#define SDAPort GPIOE //SDA引脚端口
#define SDAPin GPIO_Pin_13 //SDA引脚
#define SDAPinCLK RCC_APB2Periph_GPIOE
void IIC_Init(void); // IIC初始化
// 这里,因为SDA需要实现写和读的功能,因此写了两个,需要读的时候就调用in,需要写的时候调用out,默认out
void IIC_SDA_In(void);
void IIC_SDA_Out(void);
void IIC_Start(void); // IIC起始
void IIC_Stop(void); // IIC结束
uint8_t IIC_Wait_Ack(void);
void IIC_Ack(void); //IICAck
void IIC_NAck(void); //IICNAck
// 写一个字节
void IIC_Write_One_Byte(uint8_t byte);
// 读一个字节
uint8_t IIC_Read_One_Byte(uint8_t ack);
#endif
#include "stm32f10x.h"
#include "iic.h"
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
RCC_APB2PeriphClockCmd(SCLPinCLK,ENABLE);
RCC_APB2PeriphClockCmd(SDAPinCLK,ENABLE);
GPIO_InitStructure.GPIO_Pin = SCLPin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SCLPort, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = SDAPin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SDAPort, &GPIO_InitStructure);
GPIO_SetBits(SCLPort,SCLPin);
GPIO_SetBits(SDAPort,SDAPin);
}
void IIC_SDA_In(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SDAPin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SDAPort, &GPIO_InitStructure);
}
void IIC_SDA_Out(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SDAPin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SDAPort, &GPIO_InitStructure);
}
void IIC_Start(void)
{
IIC_SDA_Out();
GPIO_WriteBit(SDAPort,SDAPin,Bit_SET);
GPIO_WriteBit(SCLPort,SCLPin,Bit_SET);
delay_us(4);
GPIO_WriteBit(SDAPort,SDAPin,Bit_RESET);
delay_us(4);
GPIO_WriteBit(SCLPort,SCLPin,Bit_RESET);
}
void IIC_Stop(void)
{
IIC_SDA_Out();
GPIO_WriteBit(SCLPort,SCLPin,Bit_RESET);
GPIO_WriteBit(SDAPort,SDAPin,Bit_RESET);
delay_us(4);
GPIO_WriteBit(SCLPort,SCLPin,Bit_SET);
GPIO_WriteBit(SDAPort,SDAPin,Bit_SET);
delay_us(4);
}
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
IIC_SDA_In();
GPIO_WriteBit(SDAPort,SDAPin,Bit_SET);
delay_us(1);
GPIO_WriteBit(SCLPort,SCLPin,Bit_SET);
delay_us(1);
while(GPIO_ReadInputDataBit(SDAPort,SDAPin))
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
GPIO_WriteBit(SCLPort,SCLPin,Bit_RESET);
return 0;
}
void IIC_Ack(void)
{
GPIO_WriteBit(SCLPort,SCLPin,Bit_RESET);
IIC_SDA_Out();
GPIO_WriteBit(SDAPort,SDAPin,Bit_RESET);
delay_us(2);
GPIO_WriteBit(SCLPort,SCLPin,Bit_SET);
delay_us(2);
GPIO_WriteBit(SCLPort,SCLPin,Bit_RESET);
}
void IIC_NAck(void)
{
GPIO_WriteBit(SCLPort,SCLPin,Bit_RESET);
IIC_SDA_Out();
GPIO_WriteBit(SDAPort,SDAPin,Bit_SET);
delay_us(2);
GPIO_WriteBit(SCLPort,SCLPin,Bit_SET);
delay_us(2);
GPIO_WriteBit(SCLPort,SCLPin,Bit_RESET);
}
void IIC_Write_One_Byte(uint8_t byte)
{
uint8_t t;
IIC_SDA_Out();
GPIO_WriteBit(SCLPort,SCLPin,Bit_RESET);
for(t=0;t<8;t++)
{
if((byte&0x80)>>7)
GPIO_WriteBit(SDAPort,SDAPin,Bit_SET);
else
GPIO_WriteBit(SDAPort,SDAPin,Bit_RESET);
byte<<=1;
delay_us(2);
GPIO_WriteBit(SCLPort,SCLPin,Bit_SET);
delay_us(2);
GPIO_WriteBit(SCLPort,SCLPin,Bit_RESET);
delay_us(2);
}
}
uint8_t IIC_Read_One_Byte(uint8_t ack)
{
unsigned char i,receive=0;
IIC_SDA_In();
for(i=0;i<8;i++ )
{
GPIO_WriteBit(SCLPort,SCLPin,Bit_RESET);
delay_us(2);
GPIO_WriteBit(SCLPort,SCLPin,Bit_SET);
receive<<=1;
if(GPIO_ReadInputDataBit(SDAPort,SDAPin))receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();
else
IIC_Ack();
return receive;
}
代码中使用的延时函数取自正点原子官方例程提供的delay.c,delay.h,这里也一并放到了压缩包里。
网盘链接
提取码:1111
博主个人网站,欢迎访问,发现更多有趣的东西,欢迎交流。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)