IIC模拟协议华大单片机移植
本文所用为 HC32L136K8TA
使用Gpio10== SDA GpioC11==SCL
先把关键性 宏定义说明
//引脚声明
#define SCL_PORT GpioPortC
#define SCL_PIN GpioPin11
#define SDA_PORT GpioPortC
#define SDA_PIN GpioPin10
//IO方向设置
#define PC1out(n) Gpio_WriteOutputIO( GpioPortC, n, 1) //输出
#define PC0out(n) Gpio_WriteOutputIO( GpioPortC, n, 0) //输出
#define PCin(n) Gpio_GetInputIO(GpioPortC,n) //输入
//IO操作函数 置地
#define MPU_IIC_SCL_0 PC0out(GpioPin11) //SCL
#define MPU_IIC_SDA_0 PC0out(GpioPin10) //SDA
//IO操作函数 拉高
#define MPU_IIC_SCL_1 PC1out(GpioPin11) //SCL
#define MPU_IIC_SDA_1 PC1out(GpioPin10) //SDA
//IO读
#define MPU_READ_SDA PCin(10) //输入SDA
//IIC所有操作函数
void MPU_IIC_Delay(void); //MPU IIC延时函数
void MPU_IIC_Init(void); //初始化IIC的IO口
void MPU_IIC_Start(void); //发送IIC开始信号
void MPU_IIC_Stop(void); //发送IIC停止信号
void MPU_IIC_Send_Byte(uint8_t txd); //IIC发送一个字节
uint8_t MPU_IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
uint8_t MPU_IIC_Wait_Ack(void); //IIC等待ACK信号
void MPU_IIC_Ack(void); //IIC发送ACK信号
void MPU_IIC_NAck(void); //IIC不发送ACK信号
void IMPU_IC_Write_One_Byte(uint8_t daddr,uint8_t addr,uint8_t data);
uint8_t MPU_IIC_Read_One_Byte(uint8_t daddr,uint8_t addr);
先初始化SCL SDA 引脚
//初始化IIC
void MPU_IIC_Init(void)
{
stc_gpio_cfg_t stcGpioCfg;
///< 打开GPIO外设时钟门控
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
///< 端口方向配置->输入
stcGpioCfg.enDir = GpioDirOut;
stcGpioCfg.enPu = GpioPuEnable;
stcGpioCfg.enPd = GpioPdDisable;
Gpio_Init(SDA_PORT, SDA_PIN, &stcGpioCfg);
///< 端口方向配置->输出
stcGpioCfg.enDir = GpioDirOut;
stcGpioCfg.enPu = GpioPuEnable;
stcGpioCfg.enPd = GpioPdDisable;
Gpio_Init(SCL_PORT, SCL_PIN, &stcGpioCfg);
IIC_SET_SDA;
IIC_SET_SCL;
}
延时函数
//MPU IIC 延时函数
void MPU_IIC_Delay(void)
{
__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();
}
IIC起始信号 停止信号
//产生IIC起始信号 停止信号
void MPU_IIC_Start(void)
{
MPU_SDA_OUT(); //sda线输出
MPU_IIC_SDA_1;
MPU_IIC_SCL_1;
MPU_IIC_Delay();
MPU_IIC_SDA_0;//START:when CLK is high,DATA change form high to low
MPU_IIC_Delay();
MPU_IIC_SCL_0;//钳住I2C总线,准备发送或接收数据
MPU_IIC_Delay();
}
//产生IIC停止信号
void MPU_IIC_Stop(void)
{
MPU_SDA_OUT();//sda线输出
MPU_IIC_SCL_0;
MPU_IIC_SDA_0;//STOP:when CLK is high DATA change form low to high
MPU_IIC_Delay();
MPU_IIC_SCL_1;
MPU_IIC_SDA_1;//发送I2C总线结束信号
MPU_IIC_Delay();
}
主动应答和非应答
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
uint8_t MPU_IIC_Wait_Ack(void)
{
uint8_t ucErrTime=0;
MPU_SDA_IN(); //SDA设置为输入
MPU_IIC_SDA_1;MPU_IIC_Delay();
MPU_IIC_SCL_1;MPU_IIC_Delay();
while(MPU_READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
MPU_IIC_Stop();
return 1;
}
}
MPU_IIC_SCL_0;//时钟输出0
return 0;
}
//产生ACK应答
void MPU_IIC_Ack(void)
{
MPU_IIC_SCL_0;
MPU_SDA_OUT();
MPU_IIC_SDA_0;
MPU_IIC_Delay();
MPU_IIC_SCL_1;
MPU_IIC_Delay();
MPU_IIC_SCL_0;
}
//不产生ACK应答
void MPU_IIC_NAck(void)
{
MPU_IIC_SCL_0;
MPU_SDA_OUT();
MPU_IIC_SDA_1;
MPU_IIC_Delay();
MPU_IIC_SCL_1;
MPU_IIC_Delay();
MPU_IIC_SCL_0;
}
发送一个字节 读取一个字节
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void MPU_IIC_Send_Byte(uint8_t txd)
{
uint8_t t;
MPU_SDA_OUT();
MPU_IIC_SDA_0;
MPU_IIC_Delay();
for(t=0;t<8;t++)
{
if((txd&0x80)>>7)
MPU_IIC_SDA_1;
else
MPU_IIC_SDA_0;
txd<<=1;
MPU_IIC_Delay();
MPU_IIC_SCL_1;
MPU_IIC_Delay();
MPU_IIC_SCL_0;
MPU_IIC_Delay();
}
MPU_IIC_SCL_0;
MPU_IIC_Delay();
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
uint8_t MPU_IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
MPU_SDA_IN();//SDA设置为输入
MPU_IIC_Delay();
for(i=0;i<8;i++ )
{
receive<<=1;
MPU_IIC_SCL_1;
MPU_IIC_Delay();
if(READ_SDA)
receive|=0x01;
MPU_IIC_SCL_0;
MPU_IIC_Delay();
}
if (!ack)
MPU_IIC_NAck();//发送nACK
else
MPU_IIC_Ack(); //发送ACK
return receive;
}