一、简介
由飞利浦主导开发的片间互联协议。iic通信使用三线(sda scl以及gnd,不包括电源线),极大程度上减少了对ic的io口的占用。同时iic支持多主机以及多从机,方便了程序的设计。
二、协议层简介
在iic总线上scl的电平决定了整条iic总线的有效性。
当scl出于高电平时,主机与从机可以侦测sda数据的变化,sda上的数据有效。当scl出于低电平时sda线无效,目标准备读取下一位数据。
在iic总线上,一共有四种状态:起始,0/应答,1/非应答,结束 在scl线处于高电平的状态下,这四种状态对应的sda的状态分别是: 起始: sda产生下降沿 0/ack: sda处于低电平 1/nack:sda处于高电平 结束: sda产生上升沿 同时,在iic总线启动后以及一轮通信结束后,需要将scl置1,便于其他设备快速发起以及响应iic请求。而在通信中,scl要在读取前与读取后及时置0,便于目标设备读取下一位数据。
iic帧格式
首先是起始信号,通知各设备开始传输。随后是1byte的目标设备的地址(准确的说,是7位地址加上一个读写控制位)。然后由目标设备给出ack。在主机收到ack后,可进行对应数据的读取。在数据传输部分,根据iic协议规定,每次只允许连续传输1byte,也即随后需要有一方及时给出ack,否则将超时终止传输(包括nack)。所有数据传输完毕后,主机设置结束信号。
在一次通信中,如果需要转变读写状态,需要主机重新发送起始信号、目标地址与读写状态。
三、参考实现:
基于stm32f103c6t6 HAL编写
iic.c
#include "iic.h"
//private functions
void sda(uint8_t sta) {
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, sta ? GPIO_PIN_SET : GPIO_PIN_RESET);
for (int i = 0;i < 100;i++);//delay
}
void scl(uint8_t sta) {
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, sta ? GPIO_PIN_SET : GPIO_PIN_RESET);
for (int i = 0;i < 100;i++);
}
void signal(uint8_t sig) {
sda(sig);
scl(0);
scl(1);
scl(0);
}
//public functions
HAL_StatusTypeDef iic_st(void) {
sda(1);//startup
scl(1);
sda(0);
scl(0);
return HAL_OK;
}
HAL_StatusTypeDef iic_ed(void) {
scl(0);//end
sda(0);
scl(1);
sda(1);
return HAL_OK;
}
HAL_StatusTypeDef iic_tx(uint8_t data) {
for (int i = 0;i < 8;i++) {
signal(data >> 7);
data <<= 1;
}
return HAL_OK;
}
HAL_StatusTypeDef iic_rx(GPIO_PinState* pdata) {
uint8_t pin_sta = 0, data = 0;
data = 0;
scl(0);
sda(1);
for (int i = 7;i >= 0;i--) {
scl(1);
pin_sta = HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin);
data += pin_sta<<i;
scl(0);
}
*pdata = data;
return HAL_OK;
}
HAL_StatusTypeDef iic_wait_ack(void) {
uint8_t t = 0xff;
scl(0);
sda(1);
scl(1);
while (t--) {
if (HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin) == GPIO_PIN_RESET) {
scl(0);
return HAL_OK;
}
}
iic_ed();
return HAL_TIMEOUT;
}
HAL_StatusTypeDef iic_send_ack(uint8_t ack) {
signal(ack);
return HAL_OK;
}
iic.h
#ifndef __IIC_H__
#define __IIC_H__
#include "stm32f1xx_hal.h"
#define SDA_Pin GPIO_PIN_8
#define SDA_GPIO_Port GPIOB
#define SCL_Pin GPIO_PIN_9
#define SCL_GPIO_Port GPIOB
HAL_StatusTypeDef iic_st(void);
HAL_StatusTypeDef iic_ed(void);
HAL_StatusTypeDef iic_tx(uint8_t data);
HAL_StatusTypeDef iic_rx(uint8_t* data);
HAL_StatusTypeDef iic_wait_ack(void);
HAL_StatusTypeDef iic_send_ack(uint8_t ack) ;
#endif
标签:StatusTypeDef,scl,HAL,笔记,学习,sda,iic,GPIO From: https://www.cnblogs.com/lvxylvxy/p/17924440.html