标题:
stm32模拟IIC代码(有注释)
[打印本页]
作者:
hu_junbo
时间:
2018-12-11 16:15
标题:
stm32模拟IIC代码(有注释)
stm32模拟IIC功能实现通信,代码有注释
单片机源程序如下:
#include "IIC.h"
#include "Delay.h"
//初始化IIC
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//RCC->APB2ENR|=1<<4;//先使能外设IO PORTC时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
IIC_SCL=1;
IIC_SDA=1;
}
//产生IIC起始信号
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总线,准备发送或接收数据
}
//产生IIC停止信号
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;
Delay_us(4); //hu add
IIC_SDA=1;//发送I2C总线结束信号
//Delay_us(4);// hu cut
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
//IIC_SDA=0;Delay_us(1);//hu add
SDA_IN(); //SDA设置为输入
//IIC_SDA=1;Delay_us(1);//hu cut
IIC_SCL=1;Delay_us(1);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//时钟输出0
return 0;
}
//产生ACK应答
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
Delay_us(2);
IIC_SCL=1;
Delay_us(2);
IIC_SCL=0;
}
//不产生ACK应答
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
Delay_us(2);
IIC_SCL=1;
Delay_us(2);
IIC_SCL=0;
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
IIC_SDA=(txd&0x80)>>7;
txd<<=1;
Delay_us(2); //对TEA5767这三个延时都是必须的
IIC_SCL=1;
Delay_us(2);
IIC_SCL=0;
Delay_us(2);
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC_Read_Byte(void)
{
u8 i,receive=0x00;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
Delay_us(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)
receive|= 0x01;
Delay_us(1);
}
return receive;
}
//IIC 往指定地址Address里写Data
void IIC_Write_Addr_Data(u8 address,u8 data)
{
u8 w_addr,w_data;
w_addr = address;
w_data = data;
IIC_Start();
IIC_Send_Byte(0x00);
IIC_Wait_Ack();
IIC_Send_Byte(w_addr);
IIC_Ack();
IIC_Send_Byte(w_data);
IIC_Ack();
IIC_Stop();
Delay_us(4);
}
//IIC 读指定地址Address里写Data
u8 IIC_Read_Addr_Data(u8 address)
{
u8 r_addr,data=0x00;
r_addr = address;;
IIC_Start();
IIC_Send_Byte(0x00);
IIC_Wait_Ack();
IIC_Send_Byte(r_addr);
IIC_Ack();
IIC_Start();
IIC_Send_Byte(0x01);
IIC_Wait_Ack();
data = IIC_Read_Byte();
IIC_NAck();
IIC_Stop();
Delay_us(4);
return data;
}
复制代码
所有资料51hei提供下载:
IIC.zip
(1.72 KB, 下载次数: 73)
2018-12-11 16:14 上传
点击文件名下载附件
IIC源码
下载积分: 黑币 -5
作者:
hujj
时间:
2018-12-12 13:02
找了很久这类代码,正好前天找到,抄录到自己的项目中,昨天修改编译通过,还没有测试,和楼主的代码高度一致。
作者:
hujj
时间:
2018-12-12 18:53
我有一点不明白,为什么PB7(IIC_SDA)要分别设置成输入模式和输出模式,应用过程中来回切换,而不用复用模式。希望大佬给科普一下,谢谢!
作者:
没尾巴
时间:
2018-12-12 20:30
hujj 发表于 2018-12-12 18:53
我有一点不明白,为什么PB7(IIC_SDA)要分别设置成输入模式和输出模式,应用过程中来回切换,而不用复用模 ...
输入输出是为了发送和接收数据,而复用模式是管脚使用该管脚的相应外设功能
作者:
hujj
时间:
2018-12-13 13:16
谢谢楼主热心解答,但我还是不太明白,是不是作GPIO时就应该分别设置成输入和输出模式,如果是使用引脚的其他功能时则应设置成复用模式?
不好意思,有点歪楼了,抱歉!
作者:
lidylee
时间:
2020-3-19 16:47
不知道为什么推挽输出是od
作者:
nihao12345678
时间:
2020-3-19 20:32
感谢楼主分享
作者:
hghvhgv
时间:
2020-3-20 10:41
应该要设置成复用功能吧
作者:
billaj
时间:
2020-3-20 14:04
非常谢谢分享,在下新手,我能不能贪心点问一下,STM32能不能模拟IIS的??
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1