底层代码
你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
GPIO初始化设置
这颗STM8S上,具有真·开漏功能的引脚是PB4和PB5,这两个引脚也正是片上I2C外设的默认引脚。端口设置如下:
PB4 :I2C的SCL时钟线,开漏输出模式
PB5 :I2C的SDA数据线,开漏输出模式
SCL和SDA初始化时,推荐选用高阻态输出
/**
* @brief I2C端口初始化
* @param None
* @retval None
*/
void I2C_GPIO_Init(void)
{
GPIO_Init(I2C_PORT, I2C_SDA_PIN, GPIO_MODE_OUT_OD_HIZ_SLOW);
GPIO_Init(I2C_PORT, I2C_SCL_PIN, GPIO_MODE_OUT_OD_HIZ_SLOW);
I2C_SDA_OUT(1);
I2C_SCL_OUT(1);
}
I2C主机向从机发送一个字节,都会等待从机通过SDA线返回一个“已接收(ACK)”指令。此时主机的SDA应设置为输入,而在其他环节中应该保持开漏输出。而根据不同从机的I2C时序,有时也需要将SCL设置为输入。
/**
* @brief SDA设为输出
* @param None
* @retval None
*/
void I2C_SDA_SET_OUTPUT(void)
{
GPIO_Init(I2C_PORT, I2C_SDA_PIN, GPIO_MODE_OUT_OD_HIZ_SLOW);
}
/**
* @brief SCL设为输出
* @param None
* @retval None
*/
void I2C_SCL_SET_OUTPUT(void)
{
GPIO_Init(I2C_PORT, I2C_SCL_PIN, GPIO_MODE_OUT_OD_HIZ_SLOW);
}
/**
* @brief SDA设为输入
* @param None
* @retval None
*/
void I2C_SDA_SET_INPUT(void)
{
GPIO_Init(I2C_PORT, I2C_SDA_PIN, GPIO_MODE_IN_FL_NO_IT);
}
/**
* @brief SCL设为输入
* @param None
* @retval None
*/
void I2C_SCL_SET_INPUT(void)
{
GPIO_Init(I2C_PORT, I2C_SCL_PIN, GPIO_MODE_IN_FL_NO_IT);
}
GPIO输入检测
既然有了SDA或SCL的输入设置,自然需要有判断输入值的函数。
/**
* @brief SDA输入电平检测
* @param None
* @retval 1=输入为高电平 0=输入为低电平
*/
unsigned char I2C_SDA_IN(void)
{
return (!!GPIO_ReadInputPin(I2C_PORT, I2C_SDA_PIN));
}
/**
* @brief SCL输入电平检测
* @param None
* @retval 1=输入为高电平 0=输入为低电平
*/
unsigned char I2C_SCL_IN(void)
{
return (!!GPIO_ReadInputPin(I2C_PORT, I2C_SCL_PIN));
}
模拟I2C代码
包括:
起始条件,结束条件
回从机ACK,回从机NACK: 用于主机从从机读1字节(此时主从的身份对调)后,还要向其发送请继续(ACK) 或 请停下(NACK) 信号
等待从机回ACK: 主机向从机发送1字节后,需要等待从机返回接收到(ACK) ,如果接收到的是 接收到(ACK)
从从机读1字节: 完成读1字节后,需要向从机发送请继续(ACK) 或 请停下(NACK) 信号
向从机写1细节: 完成写1字节后,需要等待从机返回接收到(ACK) 信号。
起始条件,结束条件
/**
* @brief I2C传输开始
* @param None
* @retval None
*/
void I2C_START(void)
{
I2C_SDA_SET_OUTPUT();
I2C_SDA_OUT(1);
I2C_SCL_OUT(1);
Delay_1us(10);/
I2C_SDA_OUT(0);
Delay_1us(10);
I2C_SCL_OUT(0);
Delay_1us(10);
}
/**
* @brief I2C传输结束
* @param None
* @retval None
*/
void I2C_STOP(void)
{
I2C_SDA_SET_OUTPUT();
I2C_SDA_OUT(0);
I2C_SCL_OUT(0);
Delay_1us(10);//
I2C_SCL_OUT(1);
Delay_1us(10);
I2C_SDA_OUT(1);
Delay_1us(10);
}
回从机ACK,回从机NACK
/**
* @brief MCU回复IC ACK信号
* @param None
* @retval None
*/
void I2C_SEND_ACK(void)
{
I2C_SDA_SET_OUTPUT();
I2C_SDA_OUT(0);
Delay_1us(10);//
I2C_SCL_OUT(1);
Delay_1us(10);
I2C_SCL_OUT(0);
Delay_1us(10);
}
/**
* @brief MCU回复NACK信号
* @param None
* @retval None
*/
void I2C_SEND_NACK(void)
{
I2C_SDA_SET_OUTPUT();
I2C_SDA_OUT(1);
// Delay_1us(10);///
I2C_SCL_OUT(1);
Delay_1us(10);
I2C_SCL_OUT(0);
Delay_1us(10);
}
从从机读1字节
/**
* @brief I2C MCU接收1字节
* @param ACK_CHOICE: 数据读取后主机如何回复,I2C_ACK=回复ACK I2C_NACK=回复NACK I2C_JUMP_REPLY=跳过回复
* @retval read_data: 接收的字节
*/
unsigned char I2C_READ_BYTE(unsigned char ACK_CHOICE)
{
unsigned char read_data=0;
I2C_SDA_SET_INPUT();
// I2C_SCL_OUT(0);//
// Delay_1us(10);///
for(unsigned char i=0x80; i!=0; i>>=1)
{
I2C_SCL_OUT(1);
Delay_1us(10);
if(I2C_SDA_IN() == 1)
read_data |= i;
I2C_SCL_OUT(0);
Delay_1us(10);
}
I2C_SDA_SET_OUTPUT();
I2C_SDA_OUT(1);//?????????????????
if(ACK_CHOICE==I2C_ACK) I2C_SEND_ACK();
if(ACK_CHOICE==I2C_NACK) I2C_SEND_NACK();
return read_data;
}
向从机写1字节
/**
* @brief I2C MCU发送1字节
* @param send_data: 发送的字节
* @retval ack回复: I2C_NACK=异常=检测到NACK I2C_ACK=正常=检测到ACK
*/
unsigned char I2C_SEND_BYTE(unsigned char send_data)
{
unsigned char ack=I2C_NACK; //初始值
unsigned char time_out=200; //ACK查询次数
I2C_SDA_SET_OUTPUT();
// I2C_SCL_SET_OUTPUT();
// I2C_SCL_OUT(0);
// Delay_1us(10);/
for(unsigned char i=0x80; i!=0; i>>=1)
{
if(send_data&i) I2C_SDA_OUT(1);
else I2C_SDA_OUT(0);
I2C_SCL_OUT(1);
Delay_1us(10);
I2C_SCL_OUT(0);
Delay_1us(10);
}
//开始ACK查询
I2C_SDA_SET_INPUT();
I2C_SCL_OUT(1);
while(time_out--)
{
if(I2C_SDA_IN()==1)
ack=I2C_NACK;
else
{
ack=I2C_ACK;
break;
}
Delay_1us(1);
}
I2C_SCL_OUT(0);
I2C_SDA_SET_OUTPUT();
I2C_SDA_OUT(1);//???????????????????
return ack;
}
其他代码
上述全部代码位于i2c.c 源文件中,而下列代码则全部位于i2c.h 头文件。
#ifndef __I2C_H
#define __I2C_H
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private defines -----------------------------------------------------------*/
#define I2C_PORT GPIOB
#define I2C_SDA_PIN GPIO_PIN_5
#define I2C_SCL_PIN GPIO_PIN_4
#define I2C_ACK 0 //用于接收:SDA=L=从机有回复 用于发送:回复从机ACK
#define I2C_NACK 1 //用于接收:SDA=H=从机未回复 用于发送:回复从机ACK
#define I2C_JUMP_REPLY 2 //调试用
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void I2C_GPIO_Init(void);
void I2C_SDA_SET_OUTPUT(void);
void I2C_SCL_SET_OUTPUT(void);
void I2C_SDA_SET_INPUT(void);
void I2C_SCL_SET_INPUT(void);
void I2C_SDA_OUT(unsigned char value);
void I2C_SCL_OUT(unsigned char value);
unsigned char I2C_SDA_IN(void);
unsigned char I2C_SCL_IN(void);
void I2C_START(void);
void I2C_STOP(void);
void I2C_SEND_ACK(void);
void I2C_SEND_NACK(void);
unsigned char I2C_READ_BYTE(unsigned char ACK_CHOICE);
unsigned char I2C_SEND_BYTE(unsigned char send_data);
#endif
上一篇:stm8s103-PWM输出与输入捕获
下一篇:基于IAR开发环境的STM8S模拟IIC代码
推荐阅读最新更新时间:2024-11-17 01:53
设计资源 培训 开发板 精华推荐
- LT3755IMSE-2 降压模式 1.4A LED 驱动器的典型应用电路
- ZIGBEESLK: AP13192USLK ZigBee-ready RF Transceiver Student Learning Kit
- 使用 Infineon Technologies AG 的 TDA 16846 的参考设计
- AD8532ARZ1 单电源、立体声耳机驱动器的典型应用
- FRDM-K82F: 面向Kinetis® K82、K81和K80 MCU的Freedom开发平台
- MC78M15ACTG 15V 电流升压稳压器的典型应用
- 使用 MaxLinear, Inc 的 SPX385N-1.2 的参考设计
- ROM-DK3310-F0A1E,RTX 2.0 CPU 模块开发套件 ROM-3310
- CY8CKIT-059,PSoC 5LP 原型设计套件旨在用作具有 PSoC 5LP 系列的 CY8C5888LTI-LP097 器件的开发平台
- LTC3119MPFE 5V、2MHz 宽输入稳压器的典型应用电路
- 柔灵科技陈涵:将小型、柔性的脑机接口睡眠设备,做到千家万户
- 微灵医疗李骁健:脑机接口技术正在开启意识与AI融合的新纪元
- USB Type-C® 和 USB Power Delivery:专为扩展功率范围和电池供电型系统而设计
- 景昱医疗耿东:脑机接口DBS治疗技术已实现国产替代
- 首都医科大学王长明:针对癫痫的数字疗法已进入使用阶段
- 非常见问题解答第223期:如何在没有软启动方程的情况下测量和确定软启动时序?
- 兆易创新GD25/55全系列车规级SPI NOR Flash荣获ISO 26262 ASIL D功能安全认证证书
- 新型IsoVu™ 隔离电流探头:为电流测量带来全新维度
- 英飞凌推出简化电机控制开发的ModusToolbox™电机套件
- 意法半导体IO-Link执行器电路板为工业监控和设备厂商带来一站式参考设计