gd32单片机模拟iic程序
时间: 2023-08-13 09:03:19 浏览: 61
以下是基于GD32单片机的模拟IIC程序示例:
```c
#include "gd32f10x.h"
#define SDA_PIN GPIO_PIN_7
#define SDA_GPIO_PORT GPIOB
#define SCL_PIN GPIO_PIN_6
#define SCL_GPIO_PORT GPIOB
#define IIC_SCL_H() GPIO_BOP(SCL_GPIO_PORT) = SCL_PIN
#define IIC_SCL_L() GPIO_BC(SCL_GPIO_PORT) = SCL_PIN
#define IIC_SDA_H() GPIO_BOP(SDA_GPIO_PORT) = SDA_PIN
#define IIC_SDA_L() GPIO_BC(SDA_GPIO_PORT) = SDA_PIN
#define IIC_SDA_READ() GPIO_INPUT_PORT_READ(SDA_GPIO_PORT) & SDA_PIN
/* IIC延迟函数 */
void IIC_Delay(void)
{
uint16_t i = 1000;
while(i--);
}
/* IIC初始化函数 */
void IIC_Init(void)
{
gpio_init(SDA_GPIO_PORT, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, SDA_PIN);
gpio_init(SCL_GPIO_PORT, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, SCL_PIN);
IIC_SCL_H();
IIC_SDA_H();
}
/* IIC起始信号 */
void IIC_Start(void)
{
IIC_SDA_H();
IIC_SCL_H();
IIC_Delay();
IIC_SDA_L();
IIC_Delay();
IIC_SCL_L();
}
/* IIC停止信号 */
void IIC_Stop(void)
{
IIC_SDA_L();
IIC_SCL_H();
IIC_Delay();
IIC_SDA_H();
IIC_Delay();
}
/* IIC等待应答信号 */
uint8_t IIC_Wait_Ack(void)
{
uint8_t ucErrTime = 0;
IIC_SDA_H();
IIC_Delay();
IIC_SCL_H();
IIC_Delay();
while(IIC_SDA_READ())
{
ucErrTime++;
if(ucErrTime > 250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL_L();
return 0;
}
/* IIC应答信号 */
void IIC_Ack(void)
{
IIC_SCL_L();
IIC_SDA_L();
IIC_Delay();
IIC_SCL_H();
IIC_Delay();
IIC_SCL_L();
}
/* IIC非应答信号 */
void IIC_NAck(void)
{
IIC_SCL_L();
IIC_SDA_H();
IIC_Delay();
IIC_SCL_H();
IIC_Delay();
IIC_SCL_L();
}
/* IIC发送一个字节 */
void IIC_Send_Byte(uint8_t txd)
{
uint8_t t;
IIC_SCL_L();
for(t = 0; t < 8; t++)
{
if((txd & 0x80) >> 7)
IIC_SDA_H();
else
IIC_SDA_L();
txd <<= 1;
IIC_SCL_H();
IIC_Delay();
IIC_SCL_L();
IIC_Delay();
}
}
/* IIC读取一个字节 */
uint8_t IIC_Read_Byte(unsigned char ack)
{
uint8_t i, receive = 0;
IIC_SDA_H();
for(i = 0; i < 8; i++)
{
IIC_SCL_L();
IIC_Delay();
IIC_SCL_H();
receive <<= 1;
if(IIC_SDA_READ())
receive++;
IIC_Delay();
}
if(!ack)
IIC_NAck();
else
IIC_Ack();
return receive;
}
/* IIC写数据 */
uint8_t IIC_Write(uint8_t addr, uint8_t reg, uint8_t data)
{
IIC_Start();
IIC_Send_Byte(addr << 1);
if(IIC_Wait_Ack()) {
return 1;
}
IIC_Send_Byte(reg);
if(IIC_Wait_Ack()) {
return 1;
}
IIC_Send_Byte(data);
if(IIC_Wait_Ack()) {
return 1;
}
IIC_Stop();
return 0;
}
/* IIC读数据 */
uint8_t IIC_Read(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len)
{
IIC_Start();
IIC_Send_Byte(addr << 1);
if(IIC_Wait_Ack()) {
return 1;
}
IIC_Send_Byte(reg);
if(IIC_Wait_Ack()) {
return 1;
}
IIC_Start();
IIC_Send_Byte((addr << 1) | 0x01);
if(IIC_Wait_Ack()) {
return 1;
}
while(len) {
if(len == 1) {
*buf = IIC_Read_Byte(0);
} else {
*buf = IIC_Read_Byte(1);
}
buf++;
len--;
}
IIC_Stop();
return 0;
}
/* 测试IIC读写 */
int main(void)
{
uint8_t buf[2] = {0};
IIC_Init();
IIC_Write(0xA0, 0x00, 0x01);
IIC_Read(0xA0, 0x00, buf, 2);
return 0;
}
```
在上述代码中,通过定义SDA和SCL的GPIO端口和引脚,实现了IIC总线的模拟。其中,IIC_Start、IIC_Stop、IIC_Wait_Ack、IIC_Ack、IIC_NAck、IIC_Send_Byte、IIC_Read_Byte、IIC_Write和IIC_Read分别对应IIC通信的起始信号、停止信号、等待应答信号、应答信号、非应答信号、发送一个字节、读取一个字节、写数据和读数据等操作。在主函数中,通过调用IIC_Write和IIC_Read函数测试IIC的读写操作。