【Hardware】STM32软件模拟IIC
2018-03-15 19:55
351 查看
###Date:2018.3.15
转载自: http://blog.csdn.net/pain_love/article/details/54947671
IIC总线
一、与IIC有关的知识
(1)IIC属于半双工通信方式
(2)IIC的协议
1.空闲状态:IIC的SCL和SDA两条线均处于高电平状态,此时即释放总线
2.起始信号(Start):SCL为高电平期间,SDA产生一个下降沿信号
3.停止信号(End):SCL为高电平期间,SDA产生一个上升沿信号
4.应答信号ACK: 发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
5.数据有效性:I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。即:数据在SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。
6.数据传输:在I2C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。
(3)24C02
1.写数据流程
第一步,首先是 I2C 的起始信号,接着跟上首字节,也就是我们前边讲的 I2C 的器件地
址,并且在读写方向上选择“写”操作。
第二步,发送数据的存储地址。24C02 一共256 个字节的存储空间,地址从0x00~0xFF,
我们想把数据存储在哪个位置,此刻写的就是哪个地址。
第三步,发送要存储的数据第一个字节、第二个字节„„注意在写数据的过程中,
EEPROM 每个字节都会回应一个“应答位 0”,来告诉我们写 EEPROM 数据成功,如果没有
回应答位,说明写入不成功。字
2.读数据流程:
第一步,首先是 I2C 的起始信号,接着跟上首字节,也就是我们前边讲的 I2C 的器件地
址,并且在读写方向上选择“写”操作。这个地方可能有同学会诧异,我们明明是读数据为
何方向也要选“写”呢?刚才说过了, 24C02 一共有 256 个地址,我们选择写操作,是为了
把所要读的数据的存储地址先写进去,告诉 EEPROM 我们要读取哪个地址的数据。这就如
同我们打电话,先拨总机号码( EEPROM 器件地址),而后还要继续拨分机号码(数据地址),
而拨分机号码这个动作,主机仍然是发送方,方向依然是“写”。
第二步,发送要读取的数据的地址,注意是地址而非存在 EEPROM 中的数据,通知
EEPROM 我要哪个分机的信息。
第三步,重新发送 I2C 起始信号和器件地址,并且在方向位选择“读”操作。
这三步当中,每一个字节实际上都是在“写”,所以每一个字节EEPROM 都会回应一个
“应答位0”。
第四步,读取从器件发回的数据,读一个字节,如果还想继续读下一个字节,就发送一
个“应答位 ACK(0)”,如果不想读了,告诉EEPROM,我不想要数据了,别再发数据了,那
就发送一个“非应答位 NAK(1)”
3.24C02地址
24C02的 7 位地址中,其中高 4 位是固定的 0b1010,而低 3 位的地址取决于具体电路的设计,由芯片上的 A2、 A1、 A0 这 3 个引脚的实际电平决定,高为1,低为0.最低位是数据方向位(R/W)0表示接下来要发送数据(写),1表示接下来是请求数据(读)。
二、用到的知识
1. GPIO、串口
2. IIC、24C02
三、功能
先在24c02的一个地址中写入一个字符,然后在读取该位置的字符并通过串口显示出来。
[cpp] view
plain copy
#include "iic.h"
#define iicsda PBout(7)
#define iicscl PBout(6)
#define iicsdain PBin(7)
void SDAOUT(void)//sda×÷ΪÍÆÍìÊä³ö
{
GPIO_InitTypeDef GPIO_InitTypeStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_7;
GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitTypeStruct);
}
void SDAIN(void)//SDA×÷Ϊ¸¡¿ÕÊäÈë
{
GPIO_InitTypeDef GPIO_InitTypeStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_7;
GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitTypeStruct);
}
void Myiic_INIT()//IIC³õʼ»¯
{
GPIO_InitTypeDef GPIO_InitTypeStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitTypeStruct);
GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);
}
void Myiic_Start(void)//ÆðʼÐźÅ
{
SDAOUT();
iicsda=1;
iicscl=1;
delay_us(4);
iicsda=0;
delay_us(4);
iicscl=0;
}
void Myiic_Stop(void)//Í£Ö¹ÐźÅ
{
SDAOUT();
iicscl=0;
iicsda=0;
delay_us(4);
iicscl=1;
iicsda=1;
delay_us(4);
}
u8 Myiic_Wait_Ack(void)//µÈ´ýACK
{
u8 time=0;
SDAIN();
iicsda=1;
delay_us(1);
iicscl=1;
delay_us(1);
while(iicsdain)
{
time++;
if(time>250)
{
Myiic_Stop();
return 1;
}
}
iicscl=0;
return 0;
}
void Myiic_ACK(void)//²úÉúACKÓ¦´ð
{
iicscl=0;
SDAOUT();
iicsda=0;
delay_us(2);
iicscl=1;
delay_us(2);
iicscl=0;
}
void Myiic_NACK(void)//²»²úÉúÓ¦´ðλ
{
iicscl=0;
SDAOUT();
iicsda=1;
delay_us(2);
iicscl=1;
delay_us(2);
iicscl=0;
}
void Myiic_Sendbyte(u8 w)//·¢ËÍÒ»¸ö×Ö½Ú
{
u8 i;
SDAOUT();
iicscl=0;
for(i=0;i<8;i++)
{
iicsda=(w&0x80)>>7;
w<<=1;
delay_us(2);
iicscl=1;
delay_us(2);
iicscl=0;
delay_us(2);
}
}
u8 Myiic_Readbyte(unsigned char ack)//¶ÁÈ¡Ò»¸ö×Ö½Ú
{
unsigned char i=0,r=0;
SDAIN();
for(i=0;i<8;i++)
{
iicscl=0;
delay_us(2);
iicscl=1;
r<<=1;
if(iicsdain)
r++;
delay_us(1);
}
if(!ack)
Myiic_NACK();
else
Myiic_ACK();
return r;
}
转载自: http://blog.csdn.net/pain_love/article/details/54947671
IIC总线
一、与IIC有关的知识
(1)IIC属于半双工通信方式
(2)IIC的协议
1.空闲状态:IIC的SCL和SDA两条线均处于高电平状态,此时即释放总线
2.起始信号(Start):SCL为高电平期间,SDA产生一个下降沿信号
3.停止信号(End):SCL为高电平期间,SDA产生一个上升沿信号
4.应答信号ACK: 发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
5.数据有效性:I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。即:数据在SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。
6.数据传输:在I2C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。
(3)24C02
1.写数据流程
第一步,首先是 I2C 的起始信号,接着跟上首字节,也就是我们前边讲的 I2C 的器件地
址,并且在读写方向上选择“写”操作。
第二步,发送数据的存储地址。24C02 一共256 个字节的存储空间,地址从0x00~0xFF,
我们想把数据存储在哪个位置,此刻写的就是哪个地址。
第三步,发送要存储的数据第一个字节、第二个字节„„注意在写数据的过程中,
EEPROM 每个字节都会回应一个“应答位 0”,来告诉我们写 EEPROM 数据成功,如果没有
回应答位,说明写入不成功。字
2.读数据流程:
第一步,首先是 I2C 的起始信号,接着跟上首字节,也就是我们前边讲的 I2C 的器件地
址,并且在读写方向上选择“写”操作。这个地方可能有同学会诧异,我们明明是读数据为
何方向也要选“写”呢?刚才说过了, 24C02 一共有 256 个地址,我们选择写操作,是为了
把所要读的数据的存储地址先写进去,告诉 EEPROM 我们要读取哪个地址的数据。这就如
同我们打电话,先拨总机号码( EEPROM 器件地址),而后还要继续拨分机号码(数据地址),
而拨分机号码这个动作,主机仍然是发送方,方向依然是“写”。
第二步,发送要读取的数据的地址,注意是地址而非存在 EEPROM 中的数据,通知
EEPROM 我要哪个分机的信息。
第三步,重新发送 I2C 起始信号和器件地址,并且在方向位选择“读”操作。
这三步当中,每一个字节实际上都是在“写”,所以每一个字节EEPROM 都会回应一个
“应答位0”。
第四步,读取从器件发回的数据,读一个字节,如果还想继续读下一个字节,就发送一
个“应答位 ACK(0)”,如果不想读了,告诉EEPROM,我不想要数据了,别再发数据了,那
就发送一个“非应答位 NAK(1)”
3.24C02地址
24C02的 7 位地址中,其中高 4 位是固定的 0b1010,而低 3 位的地址取决于具体电路的设计,由芯片上的 A2、 A1、 A0 这 3 个引脚的实际电平决定,高为1,低为0.最低位是数据方向位(R/W)0表示接下来要发送数据(写),1表示接下来是请求数据(读)。
二、用到的知识
1. GPIO、串口
2. IIC、24C02
三、功能
先在24c02的一个地址中写入一个字符,然后在读取该位置的字符并通过串口显示出来。
[cpp] view
plain copy
#include "iic.h"
#define iicsda PBout(7)
#define iicscl PBout(6)
#define iicsdain PBin(7)
void SDAOUT(void)//sda×÷ΪÍÆÍìÊä³ö
{
GPIO_InitTypeDef GPIO_InitTypeStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_7;
GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitTypeStruct);
}
void SDAIN(void)//SDA×÷Ϊ¸¡¿ÕÊäÈë
{
GPIO_InitTypeDef GPIO_InitTypeStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_7;
GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitTypeStruct);
}
void Myiic_INIT()//IIC³õʼ»¯
{
GPIO_InitTypeDef GPIO_InitTypeStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitTypeStruct);
GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);
}
void Myiic_Start(void)//ÆðʼÐźÅ
{
SDAOUT();
iicsda=1;
iicscl=1;
delay_us(4);
iicsda=0;
delay_us(4);
iicscl=0;
}
void Myiic_Stop(void)//Í£Ö¹ÐźÅ
{
SDAOUT();
iicscl=0;
iicsda=0;
delay_us(4);
iicscl=1;
iicsda=1;
delay_us(4);
}
u8 Myiic_Wait_Ack(void)//µÈ´ýACK
{
u8 time=0;
SDAIN();
iicsda=1;
delay_us(1);
iicscl=1;
delay_us(1);
while(iicsdain)
{
time++;
if(time>250)
{
Myiic_Stop();
return 1;
}
}
iicscl=0;
return 0;
}
void Myiic_ACK(void)//²úÉúACKÓ¦´ð
{
iicscl=0;
SDAOUT();
iicsda=0;
delay_us(2);
iicscl=1;
delay_us(2);
iicscl=0;
}
void Myiic_NACK(void)//²»²úÉúÓ¦´ðλ
{
iicscl=0;
SDAOUT();
iicsda=1;
delay_us(2);
iicscl=1;
delay_us(2);
iicscl=0;
}
void Myiic_Sendbyte(u8 w)//·¢ËÍÒ»¸ö×Ö½Ú
{
u8 i;
SDAOUT();
iicscl=0;
for(i=0;i<8;i++)
{
iicsda=(w&0x80)>>7;
w<<=1;
delay_us(2);
iicscl=1;
delay_us(2);
iicscl=0;
delay_us(2);
}
}
u8 Myiic_Readbyte(unsigned char ack)//¶ÁÈ¡Ò»¸ö×Ö½Ú
{
unsigned char i=0,r=0;
SDAIN();
for(i=0;i<8;i++)
{
iicscl=0;
delay_us(2);
iicscl=1;
r<<=1;
if(iicsdain)
r++;
delay_us(1);
}
if(!ack)
Myiic_NACK();
else
Myiic_ACK();
return r;
}
相关文章推荐
- STM32软件模拟IIC
- IIC 时序分析,stm32软件模拟驱动编写
- STM32F103单片机软件模拟IIC并读取TMP112数字温度传感器
- GPIO软件模拟IIC时序--转载
- STM32 软件模拟SPI时序驱动NRF24L01
- STM32模拟IIC读写24CXX
- STM32模拟IIC
- gpio软件模拟IIC与硬件IIC驱动有什么区别
- STM32模拟 IIC
- stm32模拟iic——引脚配置、代码
- stm32模拟iic——引脚配置、代码
- STM32 模拟IIC主设备 非IIC静默模式
- STM32 IIC 通信 模拟方式
- STM32-IIC模拟从模式
- 关于STM32 的 硬件IIC和 模拟IIC理解学习
- STM32模拟IIC读写AT24CXX
- stm32软件模拟I2C
- STM32 IO 模拟IIC I2C
- MDK软件不能模拟仿真STM32的问题解决方法
- stm8 软件模拟IIC驱动PCF8563T,NOKIA5110液晶显示