概述
#ifndef __I2C_A_H
#define __I2C_A_H
#include "stm32f10x.h"
#define I2CPORT GPIOB
#define I2C_SCL GPIO_Pin_6 //时钟通信端口
#define I2C_SDA GPIO_Pin_7 //数据通信端口
#define SCL_HIGH()
{
PBout(6) = 1;
} //时钟线置高
#define SCL_LOW()
{
PBout(6) = 0;
} //时钟线置低
#define SDA_HIGH()
{
PBout(7) = 1;
} //数据线置高
#define SDA_LOW()
{
PBout(7) = 0;
} //数据线置低
#define SDA_READ PBin(7) //读数据时的pin脚定义,输入PB7口
#define SDA_IN()
{
GPIOB->CRL &= 0X0FFFFFFF;
GPIOB->CRL |= 0x80000000;
} //清零和设置输入模式
#define SDA_OUT()
{
GPIOB->CRL &= 0X0FFFFFFF;
GPIOB->CRL |= 0x30000000;
} //清零和设置输出模式
void I2C_Configuration(); //端口配置初始化
void I2C_START(); //通讯信号开始函数
void I2C_STOP(); //通讯信号结束函数
void I2C_Ack(); //主机应答函数
void I2C_NAck(); //主机非应答函数
uint8_t I2C_Wait_Ack(); //主机等待应答函数
void I2C_SEND(uint8_t byte); //主机发送单个字节函数
uint8_t I2C_READ(); //主机读取单个字节函数
void I2C_SEND_BYTE(uint8_t slaveaddr, uint8_t registeraddr, uint8_t byte); //发送到具体从机地址及相关寄存器一个字节
void I2C_SEND_BYTES(uint8_t slaveaddr, uint8_t registeraddr, uint8_t *pbuffer, uint16_t num); //发送一串数据给具体从机的相关寄存器
void I2C_READ_BYTES(uint8_t slaveaddr, uint8_t registeraddr, uint8_t *pbuffer, uint16_t num); //读取具体从机的相关寄存器一串字节
#endif
void I2C_START()
{
SDA_OUT(); //设置pin脚的方向是输出,意味着主机向从机发数据了
SCL_HIGH(); //先拉高时钟线
SDA_HIGH(); //再拉高数据线
delay_us(2); //延迟2us,延迟是有必要的,参照I2C协议写的
SDA_LOW(); //拉低数据线,触发通讯
delay_us(2); //延迟2us
SCL_LOW(); //拉低时钟线,方便数据线上的数据变化
delay_us(2); //延迟2us
}
void I2C_STOP()
{
SDA_OUT(); //设置pin脚的方向是输出,意味着主机向从机发数据了
SDA_LOW(); //先拉底数据线
SCL_HIGH(); //再拉高时钟线
delay_us(2); //延迟2us
SDA_HIGH(); //拉高数据线,终止通讯
delay_us(2); //延迟2us
}
void I2C_Ack()
{
SCL_LOW(); //SCL线先置低,方便数据线上变化数据
SDA_IN(); //SCL端口变成输入模式
SDA_LOW(); //SDA线置低,代表响应应答
delay_us(2);
SCL_HIGH(); //SCL钳住数据,数据不可变
delay_us(2);
SCL_LOW(); //结束响应的时段
SDA_HIGH(); //CPU释放数据总线
}
void I2C_NAck()
{
SCL_LOW(); //SCL线先置低,方便数据线上变化数据
SDA_IN(); //SCL端口变成输入模式
SDA_HIGH(); //SDA线置高,代表不响应应答
delay_us(2);
SCL_HIGH(); //SCL钳住数据,数据不可变
delay_us(2);
SCL_LOW(); //结束响应的时段
SDA_HIGH(); //CPU释放数据总线
}
int I2C_Wait_Ack()
{
uint8_t ucErrTime = 0; //记录超时的计数参数
SDA_IN(); //SDA设为输入,说明主机现在处于接收数据状态,等待从机发送数据
SDA_HIGH();
delay_us(1);
SCL_HIGH();
delay_us(1);
while (SDA_READ) //非应答时进入此状态
{
ucErrTime++; //计数加
if (ucErrTime > 250) //计数大于250说明无响应,终止通讯
{
I2C_STOP();
return 1;
}
}
SCL_LOW(); //拉低时钟线,等待数据变化
delay_us(1);
return 0;
}
void I2C_SEND(uint8_t byte)
{
for (t = 0; t < 8; t++) //按位显示状态,传输一个字节,也就是8位状态
{
if (byte & 0x80) //判断字节的最高位,如果为1,输出高电平,如果为0,输出低电平
{
SDA_HIGH();
}
else
{
SDA_LOW();
}
byte <<= 1; //移位操作,遍历总共的8位
delay_us(2);
SCL_HIGH(); //钳住数据,高电平数据线上的状态就改变不了了
delay_us(2);
SCL_LOW(); //置低位,为下次数据线上的状态改变做准备
}
}
uint8_t I2C_READ()
{
for (i = 0; i < 8; i++)
{
SCL_LOW(); //scl拉低,sda总线变化
delay_us(2); //
SCL_HIGH(); //scl拉高,sda总线锁死
receive = (receive << 1) | SDA_READ; //读取数据总线的数据,按位来读取,从高位读到低位,移位顺延
delay_us(2);
}
}
void I2C_SEND_BYTE(uint8_t slaveaddr, uint8_t registeraddr, uint8_t byte)
{
I2C_START(); //通讯开始
I2C_SEND(slaveaddr); //先发送从机的地址,寻址从机
I2C_Wait_Ack(); //得到回应,说明,电路中有这个外设器件
I2C_SEND(registeraddr); //寻址这个器件中的相关寄存器
I2C_Wait_Ack(); //得到回应,说明这个寄存器存在
I2C_SEND(byte); //发送一个字节
I2C_Wait_Ack(); //等待回应
}
void I2C_SEND_BYTES(uint8_t slaveaddr, uint8_t registeraddr, uint8_t *pbuffer, uint16_t num)
{
I2C_START(); //开始通讯
I2C_SEND(slaveaddr); //寻址从机
I2C_Wait_Ack(); //等待回应
I2C_SEND(registeraddr); //寻址寄存器
I2C_Wait_Ack(); //等待回应
for (t = 0; t < num; t++) //发送数组中的数据
{
I2C_SEND(*(pbuffer + t));
I2C_Wait_Ack(); //每发送一个字节,都需要一个应答
}
I2C_STOP(); //终止通讯
}
void I2C_READ_BYTES(uint8_t slaveaddr, uint8_t registeraddr, uint8_t *pbuffer, uint16_t num)
{
I2C_START(); //开始通讯
I2C_SEND(slaveaddr); //寻址从机
I2C_Wait_Ack(); //等待回应
I2C_SEND(registeraddr); //寻址寄存器
I2C_Wait_Ack(); //等待回应
I2C_START(); //重新通讯
I2C_SEND(slaveaddr + 1); //改为读数据
I2C_Wait_Ack(); //等待回应
for (t = 0; t < num; t++) //存储数据
{
*(pbuffer + t) = I2C_READ();
if (t == num - 1) //字节没发完,必须给出应答,发完的给个非应答信号
{
I2C_Ack();
}
else
{
I2C_NAck();
}
}
I2C_STOP(); //通讯结束
}
最后
以上就是幸福服饰为你收集整理的软件IIC的全部内容,希望文章能够帮你解决软件IIC所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复