单片机
返回首页

STM32F103标准库开发---IIC主控实验---普通I/O口模拟---底层驱动程序

2022-09-20 来源:csdn

IIC底层驱动程序

这次I是普通I/O端口模拟IIC通信实验

具体引脚配置如下:

image.png

IIC主控实验----底层驱动GPIO配置

GPIO初始化配置

具体代码如下:


//初始化IIC

void IIC_Init(void)

{      

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //使能GPIOB时钟

   

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); //PB6,PB7 输出高电平---空闲状态

}


时钟线(SCL)—GPIO功能配置

在IIC通信中,主控的时钟线(SCL) 一直是输出状态

具体程序如下:


//时钟线(SCL):PB6输出---高电平

#define SCL_H  GPIO_SetBits(GPIOB,GPIO_Pin_6)  


//时钟线(SCL):PB6输出---低电平

#define SCL_L  GPIO_ResetBits(GPIOB,GPIO_Pin_6)


数据线(SDA)—GPIO功能配置

由于IIC通信是半双工通信方式

因而数据线(SDA)可能会是数据输入,也可能是数据输出。


数据线(SDA)输入模式

//数据线(SDA):PB7输入

#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}


//读取PB7的电平

#define READ_SDA  GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)


数据线(SDA)输出模式

//数据线(SDA):PB7输出

#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}


//数据线(SDA):PB7输出---高电平

#define SDA_H  GPIO_SetBits(GPIOB,GPIO_Pin_7)

//数据线(SDA):PB7输出---低电平

#define SDA_L  GPIO_ResetBits(GPIOB,GPIO_Pin_7)


IIC主控实验----底层驱动程序

开始信号

当时钟线SCL 为高电平时,数据线SDA 由高电平向低电平跳变。

具体程序如下:


void IIC_Start(void)//开始信号

{

SDA_OUT(); //数据线(SDA)输出模式

SDA_H; //数据线(SDA)输出高电平

SCL_H; //时钟线(SCL)输出高电平

delay_us(5);

SDA_L; //数据线(SDA)输出低电平

delay_us(5);

SCL_L; //时钟线(SCL)输出低电平

}


终止信号

当时钟线SCL 为高电平时,数据线SDA 由低电平向高电平跳变。

具体程序如下:


void IIC_Stop(void)//终止信号

{

SDA_OUT(); //数据线(SDA)输出模式

SCL_L; //时钟线(SCL)输出低电平

SDA_L; //数据线(SDA)输出低电平

delay_us(5);

SCL_H; //时钟线(SCL)输出高电平

SDA_H; //数据线(SDA)输出高电平

delay_us(5);

}


应答信号

我们这里写的是IIC主控程序,在读取从控数据的时候,需要回复应答信号。

产生应答信号,表示接收数据成功。

具体程序如下:


void IIC_Ack(void)//产生应答信号

{

SCL_L; //时钟线(SCL)输出低电平

SDA_OUT(); //数据线(SDA)输出模式

SDA_L; //数据线(SDA)输出低电平

delay_us(2);

SCL_H; //时钟线(SCL)输出高电平

delay_us(5);

SCL_L; //时钟线(SCL)输出低电平

}


产生非应答信号,表示接收数据失败。

具体程序如下:


void IIC_NAck(void)//不产生应答信号

{

SCL_L; //时钟线(SCL)输出低电平

SDA_OUT(); //数据线(SDA)输出模式

SDA_H; //数据线(SDA)输出高电平

delay_us(2);

SCL_H; //时钟线(SCL)输出高电平

delay_us(5);

SCL_L; //时钟线(SCL)输出低电平

}


IIC主控程序,在写入数据到从控的时候,需要等待应答信号。


//返回值:1,接收应答失败

//        0,接收应答成功

u8 IIC_Wait_Ack(void)//等待应答信号

{

int uc=0;

SDA_IN(); //数据线(SDA)输入模式

SDA_H;  delay_us(1);

SCL_H;  delay_us(1);

while(READ_SDA)

{

uc++;

if(uc>250)//接收应答失败

{

IIC_Stop();//发送终止信号

return 1;

}

}

SCL_L;

return 0;

}


数据传输

IIC总线进行数据传送时,时钟线(SCL)上的信号为高电平期间,数据线(SDA)上的数据必须保持稳定。

只有在时钟线(SCL)上的信号为低电平期间,数据线(SCL)上的高电平或低电平状态才允许变化。


在这里插入图片描述

输出到数据线(SDA)上的每个字节必须是8位

数据传送时,先传送最高位(MSB),后传送最低位(LSB)

每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)


在这里插入图片描述

IIC主控发送一个字节数据

具体程序如下:


void IIC_Send_Byte(u8 txdata)//发送一个字节数据---高位在前,低位在后

{

SDA_OUT(); //数据线(SDA)输出模式

SCL_L;

for(int t=0;t<8;t++) //高位在前,低位在后。

{

if((txdata&0x80)>>7)    SDA_H;

else                SDA_L;

txdata<<=1;

delay_us(2);

SCL_H;

delay_us(2);

SCL_L;

delay_us(2);

}

}


IIC主控接收一个字节数据

具体程序如下:


u8 IIC_Read_Byte(unsigned char ack)//读取一个字节数据---ack=1时,发送ACK,ack=0,发送nACK

{

unsigned char rxdata=0,i;

SDA_IN(); //数据线(SDA)输入模式

for(i=0;i<8;i++)

{

SCL_L;

delay_us(2);

SCL_H;

rxdata<<=1;

if(READ_SDA) rxdata++;

delay_us(1);

}

if(!ack)   IIC_NAck();

else       IIC_Ack();

return rxdata;

}

进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 1瓦线性调频增强器

  • 12V 转 28V DC-DC 变换器(基于 LM2585)

  • 红外遥控音量控制

  • LM317过压保护

  • 12V转110V/220V 500W逆变器

  • DS1669数字电位器

    相关电子头条文章