标题:
改进型STM32模拟IIC 源程序
[打印本页]
作者:
isdasjkdajk
时间:
2019-11-2 20:49
标题:
改进型STM32模拟IIC 源程序
最近在研究MPU6050,但是MPU6050的底层驱动又不想自己写,那怎么办呢我就想到了去移植正点原子的代码,但是打开代码一看需要修改寄存器值 那意味着要去翻数据是手册,我这个人本身比较懒不想去翻,也为了以后不翻,于是乎我想到了自己动手写模拟IIC的代码。写的过程中我就发现一个问题为什么每次都要管脚切换方向非常麻烦(本人非常烦这一点),于是乎我就在想有没有办法不切换方向去读数据。最后我终于在野火的树上找到了这样一句话“STM32的管脚在输出模式下也可以读到数据”,起初我对这句话半信半疑于是我自己做了一波实验,把管脚配置成输出模式(推挽和开漏都配置了)结果真的能读到数据不过要使用函数GPIO_ReadInputDataBit去读IDR寄存器的值。用位带操作就是不行。然后抱着这个结果我就开始了写IIC。在这里对IIC协议不再介绍,毕竟网上大佬挺多的随便改都能找到协议的说明。我的代码最大的好处就是容易移植容易修改废话不多说了开始附上代码。
单片机源程序如下:
#include "bsp_i2c_ee.h"
/*适用于STM32F103系列*/
void IIC_Init(void) //初始化IIC总线所用到的端口
{
GPIO_InitTypeDef IICBUS;
IICBUS.GPIO_Mode = GPIO_Mode_Out_OD;
IICBUS.GPIO_Speed = GPIO_Speed_50MHz;
IICBUS.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //修改
GPIO_Init(GPIOA,&IICBUS); //修改
GPIO_SetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1); // 修改 //拉高总线(释放总线)不进行操作
}
static void IIC_Delay(void) //IIC延时函数对总线速度进行控制
{
u8 i = 0;
/*
下面的时间是通过逻辑分析仪测试得到的。
工作条件:CPU主频72MHz ,MDK编译环境,1级优化
循环次数为10时,SCL频率 = 205KHz
循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us
循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us
*/
for (i = 0; i < 7; i++);
}
// IIC起始信号
void IIC_Start(void)
{
SDA_SETB;
SCL_SETB;
IIC_Delay();
SDA_CLR;
IIC_Delay();
SCL_CLR;
}
// IIC停止信号
void IIC_Stop(void)
{
SCL_CLR;
SDA_CLR;
SCL_SETB;
IIC_Delay();
SDA_SETB;
IIC_Delay();
}
//IIC主机产生应答信号
void IIC_Ack(void)
{
SCL_CLR;
SDA_CLR;
IIC_Delay();
SCL_SETB;
IIC_Delay();
SCL_CLR;
}
//IIC主机不应答
void IIC_Nack(void)
{
SCL_CLR;
SDA_SETB;
IIC_Delay();
SCL_SETB;
IIC_Delay();
SCL_CLR;
}
//IIC主机等待从机应答
u8 IIC_WaitAck(void)
{
u8 timeout = 0;
SDA_SETB;
IIC_Delay();
SCL_SETB;
IIC_Delay();
while(SDA_Read)//读取
{
if(++timeout>250)
{
IIC_Stop();
return 1; //超时没有应答
}
}
SCL_CLR;
return 0; //应答了
}
//IIC总线发送一组数据
void IIC_SendByte(u8 TXData)
{
u8 i = 0;
SCL_CLR;
for(i = 0;i<8;i++)
{
if(TXData&0x80)
{
SDA_SETB;
}
else
{
SDA_CLR;
}
IIC_Delay();
SCL_SETB;
IIC_Delay();
SCL_CLR;
TXData<<=1;
}
}
//读取一byte数据
//ack = 1;应答
//ack = 0;不应答
u8 IIC_ReadByte(u8 ack)
{
u8 Receive = 0;
u8 i = 0;
for(i=0;i<8;i++)
{
SCL_CLR;
IIC_Delay();
SCL_SETB;
Receive<<=1; //先左移动一位空位置出来
if(SDA_Read)
{
Receive ++;
}
IIC_Delay();
}
if(ack)
{
IIC_Ack(); //产生应答信号
}
else
{
IIC_Nack();//不产生应答信号
}
return Receive;
}
//返回0检测到了设备
//返回1没有检测到设备
//参数是你所要检测的设备的地址
u8 IIC_CheckDevice(u8 __Address)//检测外部是否挂载了从机
{
u8 ucAck = 0;
IIC_Init();
IIC_Start();
IIC_SendByte(__Address|IIC_Wr);
ucAck = IIC_WaitAck();
IIC_Stop();
return ucAck;
}
复制代码
全部资料51hei下载地址:
i2c.zip
(1.82 KB, 下载次数: 31)
2019-11-2 20:49 上传
点击文件名下载附件
模拟IIC
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1