GD32 GPIO模拟IIC

362 阅读2分钟

本文已参与 新人创作礼 活动,一起开启掘金创作之路。 **IIC协议:**IC(inter-integrated Circuit集成电路总线)总线支持设备之间的短距离通信,用于处理器和一些外围设备之间的接口,它需要两根信号线来完成信息交换。IIC的一个特殊工艺优势是微控制器只需要两个通用I/O引脚和软件即可控制芯片网络。

I²C 总线是一个多主机的总线。这就是说可以连接多于一个能控制总线的器件到总线。,IIC采用串行数据传输的方式进行数据传输,串行数据(SDA)和串行时钟(SCL) 线在连接到总线的器件间传递信息。每个器件都有一个唯一的地址识别(无论是微控制器、LCD驱动器、存储器或键盘接口),而且都可以作为一个发送器或接收器(由器件的功能决定)。很明显,LCD驱动器只是一个接收器,而存储器则既可以接收又可以发送数据。

由于在做一个GD项目的时候采用硬件IIC时踩了很多的坑,且GD32的硬件存在很多的不确定性,所以最后还是决定采用模拟IIC的方式。模拟IIC可以很确当的知道控制的电平状态。

IIC所有的操作函数:

void IIC_Init(void);                                               //初始化IIC的IO口                 
void IIC_Start(void);                                           //发送IIC开始信号
void IIC_Stop(void);                                             //发送IIC停止信号
void IIC_Send_Byte(uint8_t txd);                        //IIC发送一个字节
uint8_t IIC_Read_Byte(unsigned char ack);       //IIC读取一个字节
uint8_t IIC_Wait_Ack(void);                                //IIC等待ACK信号
void IIC_Ack(void);                                            //IIC发送ACK信号
void IIC_NAck(void);                                          //IIC不发送ACK信号

#include "myiic.h"
#include "gd32f30x.h"
#include "delay.h"

void IIC_Init(void)
{
rcu_periph_clock_enable(RCU_GPIOB);

    gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8 );    //SCL
gpio_init(GPIOB, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_9);    //SDA

IIC_SCL(1);
IIC_SDA(1);
}

void IIC_Start(void)
{
SDA_OUT();     //sda线输出
IIC_SDA(1);            
IIC_SCL(1);
delay_us(4);
IIC_SDA(0);//START:when CLK is high,DATA change form high to low 
delay_us(4);
IIC_SCL(0);//钳住I2C总线,准备发送或接收数据 
}

void IIC_Stop(void)
{
SDA_OUT();//sda线输出
IIC_SCL(0);
IIC_SDA(0);//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL(1); 
IIC_SDA(1);//发送I2C总线结束信号
delay_us(4);                                   
}

uint8_t IIC_Wait_Ack(void)
{
uint8_t ucErrTime=0;
SDA_IN();      //SDA设置为输入  
IIC_SDA(1);delay_us(1);       
IIC_SCL(1);delay_us(1);     
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL(0);//时钟输出0        
return 0;  

void IIC_Ack(void)
{
IIC_SCL(0);
SDA_OUT();
IIC_SDA(0);
delay_us(2);
IIC_SCL(1);
delay_us(2);
IIC_SCL(0);
}

void IIC_NAck(void)
{
IIC_SCL(0);
SDA_OUT();
IIC_SDA(1);
delay_us(2);
IIC_SCL(1);
delay_us(2);
IIC_SCL(0);
}    

void IIC_Send_Byte(uint8_t txd)
{                        
uint8_t t;   
SDA_OUT();         
IIC_SCL(0);//拉低时钟开始数据传输
for(t=0;t<8;t++)
{              
//            IIC_SDA((txd&0x80)>>7);
IIC_SDA((txd&0X80)>>7);
txd<<=1;       
delay_us(2);   //对TEA5767这三个延时都是必须的
IIC_SCL(1);
delay_us(2); 
IIC_SCL(0);    
delay_us(2);
}     

uint8_t IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
IIC_SCL(0); 
delay_us(2);
IIC_SCL(1);
receive<<=1;
if(READ_SDA)receive++;   
delay_us(1); 
}                     
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK   
return receive;
}