stm8s 使用IO口模拟I2C
时间:2019-09-30
本文章向大家介绍stm8s 使用IO口模拟I2C,主要包括stm8s 使用IO口模拟I2C使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
刚入职不久,下面是使用stm8s005k6写的eeprom驱动程序。
#include "bsp_i2c.h" /* 在stm8平台下移植,只需要改下面的宏定义即可 */ #define PORT_I2C_SCL GPIOC #define PIN_I2C_SCL GPIO_PIN_1 #define PORT_I2C_SDA GPIOC #define PIN_I2C_SDA GPIO_PIN_2 static void i2c_Delay(void); static void i2c_PinModeOutput(void); static void i2c_PinModeInput(void); static void i2c_SCL(uint8_t stat); static void i2c_SDA(uint8_t stat); static uint8_t i2c_ReadSDA(void); /* * 函 数 名: i2c_InitGpio * 功能说明: 初始化IIC接口 * 形 参: 无 * 返 回 值: 无 */ void i2c_InitGpio(void) { GPIO_Init(PORT_I2C_SCL, PIN_I2C_SCL, GPIO_MODE_OUT_PP_LOW_FAST); GPIO_Init(PORT_I2C_SDA, PIN_I2C_SDA, GPIO_MODE_OUT_PP_LOW_FAST); i2c_Stop(); } /* * 函 数 名: i2c_Delay * 功能说明: 延时函数 * 形 参: 无 * 返 回 值: 无 */ static void i2c_Delay(void) { uint8_t time = 10; while (time--); } /* * 函 数 名: i2c_PinModeOutput * 功能说明: 将SDA线的端口设置为输出 * 形 参: 无 * 返 回 值: 无 */ static void i2c_PinModeOutput(void) { GPIO_Init(PORT_I2C_SDA, PIN_I2C_SDA, GPIO_MODE_OUT_PP_LOW_FAST); } /* * 函 数 名: i2c_PinModeOutput * 功能说明: 将SDA线的端口设置为输入 * 形 参: 无 * 返 回 值: 无 */ static void i2c_PinModeInput(void) { GPIO_Init(PORT_I2C_SDA, PIN_I2C_SDA, GPIO_MODE_IN_FL_NO_IT); } /* * 函 数 名: i2c_SCL * 功能说明: 控制SCL线电平状态 * 形 参: stat:0 输出低电平,1 输出高电平 * 返 回 值: 无 */ static void i2c_SCL(uint8_t stat) { if (stat) { GPIO_WriteHigh(PORT_I2C_SCL, PIN_I2C_SCL); } else { GPIO_WriteLow(PORT_I2C_SCL, PIN_I2C_SCL); } } /* * 函 数 名: i2c_SDA * 功能说明: 控制SDA线电平状态 * 形 参: stat:0 输出低电平,1 输出高电平 * 返 回 值: 无 */ static void i2c_SDA(uint8_t stat) { if (stat) { GPIO_WriteHigh(PORT_I2C_SDA, PIN_I2C_SDA); } else { GPIO_WriteLow(PORT_I2C_SDA, PIN_I2C_SDA); } } /* * 函 数 名: i2c_ReadSDA * 功能说明: 读取SDA线电平状态 * 形 参: 无 * 返 回 值: 0 或 1 */ static uint8_t i2c_ReadSDA(void) { if (GPIO_ReadInputPin(PORT_I2C_SDA, PIN_I2C_SDA)) { return 1; } else { return 0; } } /* * 函 数 名: i2c_Start * 功能说明: IIC总线起始信号 * 形 参: 无 * 返 回 值: 无 */ void i2c_Start(void) { i2c_PinModeOutput(); i2c_SDA(1); i2c_Delay(); i2c_SCL(1); i2c_Delay(); i2c_SDA(0); i2c_Delay(); i2c_SCL(0); i2c_Delay(); } /* * 函 数 名: i2c_Stop * 功能说明: IIC总线停止信号 * 形 参: 无 * 返 回 值: 无 */ void i2c_Stop(void) { i2c_PinModeOutput(); i2c_SCL(0); i2c_SDA(0); i2c_Delay(); i2c_SCL(1); i2c_Delay(); i2c_SDA(1); i2c_Delay(); } /* * 函 数 名: i2c_WriteByte * 功能说明: IIC总线写数据 * 形 参: _ucByte:写入的一个字节数据 * 返 回 值: 无 */ void i2c_WriteByte(uint8_t _ucByte) { uint8_t i; i2c_PinModeOutput(); i2c_SCL(0); i2c_Delay(); for (i = 0; i < 8; i++) { if (_ucByte & 0x80) { i2c_SDA(1); } else { i2c_SDA(0); } _ucByte = _ucByte << 1; i2c_SCL(1); i2c_Delay(); i2c_SCL(0); i2c_Delay(); } i2c_SDA(1); } /* * 函 数 名: i2c_ReadByte * 功能说明: IIC总线读数据 * 形 参: 无 * 返 回 值: recv:读取的一个字节数据 */ uint8_t i2c_ReadByte(void) { uint8_t i; uint8_t recv = 0; i2c_PinModeOutput(); i2c_SDA(1); i2c_Delay(); i2c_PinModeInput(); for (i = 0; i < 8; i++) { recv = recv << 1; i2c_SCL(1); i2c_Delay(); if (i2c_ReadSDA()) { recv |= 0x01; } else { recv |= 0x00; } i2c_SCL(0); i2c_Delay(); } return recv; } /* * 函 数 名: i2c_Ack * 功能说明: IIC总线主机主动应答 * 形 参: 无 * 返 回 值: 无 */ void i2c_Ack(void) { i2c_PinModeOutput(); i2c_SCL(0); i2c_SDA(0); i2c_Delay(); i2c_SCL(1); i2c_Delay(); i2c_SCL(0); } /* * 函 数 名: i2c_NAck * 功能说明: IIC总线主机主动非应答 * 形 参: 无 * 返 回 值: 无 */ void i2c_NAck(void) { i2c_PinModeOutput(); i2c_SCL(0); i2c_SDA(1); i2c_Delay(); i2c_SCL(1); i2c_Delay(); i2c_SCL(0); } /* * 函 数 名: i2c_CheckAck * 功能说明: IIC总线检测应答信号 * 形 参: 无 * 返 回 值: 0 应答信号,1 非应答信号 */ uint8_t i2c_CheckAck(void) { uint8_t time = 0; i2c_PinModeOutput(); i2c_SDA(1); i2c_Delay(); i2c_SCL(1); i2c_Delay(); i2c_PinModeInput(); while (i2c_ReadSDA()) { time++; if (time >= 100) { return 1; } } i2c_SCL(0); return 0; }
#ifndef __BSP_I2C_H__ #define __BSP_I2C_H__ #include "stm8s.h" #define I2C_WR ((uint8_t) 0) /* 写控制bit */ #define I2C_RD ((uint8_t) 1) /* 读控制bit */ #define ACK ((uint8_t) 0) #define NOACK ((uint8_t) 1) void i2c_InitGpio(void); void i2c_Start(void); void i2c_Stop(void); void i2c_WriteByte(uint8_t _ucByte); uint8_t i2c_ReadByte(void); void i2c_Ack(void); void i2c_NAck(void); uint8_t i2c_CheckAck(void); #endif /* __BSP_I2C_H__ */
#include "m24256_driver.h" #include "bsp_i2c.h" #include "modbus_driver.h" //uint8_t g_ucIsEEPROMBusy; /* * 函 数 名: M24256_Init * 功能说明: 初始化 * 形 参: 无 * 返 回 值: 无 */ void M24256_Init(void) { i2c_InitGpio(); } /* * 函 数 名: M24256_WriteByte * 功能说明: 写一个字节 * 形 参: _usAddress:地址 * _ucByte:数据 * 返 回 值: 无 */ uint8_t M24256_WriteByte(uint16_t _usAddress, uint8_t _ucByte) { uint16_t i; for (i = 0; i < 3000; i++) { i2c_Start(); i2c_WriteByte(EE_DEV_ADDR | I2C_WR); /* 选中器件 + 写 */ if (i2c_CheckAck() == ACK) { break; } } if (i >= 3000) { i2c_Stop(); return 0; } /* 发送地址 */ i2c_WriteByte((_usAddress & 0xFF00) >> 8); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 2; } i2c_WriteByte(_usAddress & 0x00FF); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 3; } /* 读数据 */ i2c_WriteByte(_ucByte); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 4; } i2c_Stop(); return 5; } /* * 函 数 名: M24256_ReadByte * 功能说明: 读一个字节 * 形 参: _usAddress:地址 * 返 回 值: recv:读取到的一个字节数据 */ uint8_t M24256_ReadByte(uint16_t _usAddress) { uint8_t recv = 0; uint16_t i; for (i = 0; i < 3000; i++) { i2c_Start(); i2c_WriteByte(EE_DEV_ADDR | I2C_WR); /* 选中器件 + 写 */ if (i2c_CheckAck() == ACK) { break; } } if (i >= 3000) { i2c_Stop(); return 0; } /* 发送地址 */ i2c_WriteByte((_usAddress & 0xFF00) >> 8); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } i2c_WriteByte(_usAddress & 0x00FF); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } i2c_Start(); i2c_WriteByte(EE_DEV_ADDR | I2C_RD); /* 选中器件 + 读 */ if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } recv = i2c_ReadByte(); i2c_NAck(); i2c_Stop(); return recv; } /* * 函 数 名: M24256_ReadBlock * 功能说明: 从串行EEPROM指定地址处开始读取若干数据 * 形 参: _usAddress : 起始地址 * _usSize : 数据长度,单位为字节 * _pReadBuf : 存放读到的数据的缓冲区指针 * 返 回 值: 0 表示失败,1表示成功 */ unsigned char M24256_ReadBlock(unsigned char *_pReadBuf, unsigned short _usSize, unsigned short _usAddress) { uint16_t i; for (i = 0; i < 3000; i++) { i2c_Start(); i2c_WriteByte(EE_DEV_ADDR | I2C_WR); /* 选中器件 + 写 */ if (i2c_CheckAck() == ACK) { break; } } if (i >= 3000) { i2c_Stop(); return 0; } /* 发送地址 */ i2c_WriteByte((_usAddress & 0xFF00) >> 8); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } i2c_WriteByte(_usAddress &0x00FF); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } i2c_Start(); i2c_WriteByte(EE_DEV_ADDR | I2C_RD); /* 选中器件 + 读 */ if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } /* 循环读取数据 */ for (i = 0; i < _usSize; i++) { _pReadBuf[i] = i2c_ReadByte(); if (i != _usSize - 1) { i2c_Ack(); } else { i2c_NAck(); /* 读完最后一个字节,主机发送非应答 */ } } i2c_Stop(); return 1; } /* * 函 数 名: M24256_WriteBlock * 功能说明: 向串行EEPROM指定地址写入若干数据,采用页写操作提高写入效率 * 形 参: _usAddress : 起始地址 * _usSize : 数据长度,单位为字节 * _pWriteBuf : 存放读到的数据的缓冲区指针 * 返 回 值: 0 表示失败,1表示成功 */ unsigned char M24256_WriteBlock(unsigned char *_pWriteBuf, unsigned short _usSize, unsigned short _usAddress) { uint16_t i, m; uint16_t usAddr; usAddr = _usAddress; for (i = 0; i < _usSize; i++) { if ((i == 0) || (usAddr & (EE_PAGE_SIZE - 1)) == 0) { i2c_Stop(); /* 重复发送起始信号,eeprom要重新开始写要等待10ms左右 */ for (m = 0; m < 3000; m++) { i2c_Start(); i2c_WriteByte(EE_DEV_ADDR | I2C_WR); if (i2c_CheckAck() == ACK) { break; } } if (m >= 3000) { i2c_Stop(); /* 写eeprom超时 */ return 0; } /* 发送地址 */ i2c_WriteByte((usAddr & 0xFF00) >> 8); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } i2c_WriteByte(usAddr & 0x00FF); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } } /* 写入数据 */ i2c_WriteByte(_pWriteBuf[i]); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } usAddr++; } i2c_Stop(); return 1; }
#ifndef __M24256_DRIVER_H__ #define __M24256_DRIVER_H__ #include "stm8s.h" #define EE_MODEL_NAME "M24256" #define EE_DEV_ADDR 0xA0 /* 设备地址 */ #define EE_PAGE_SIZE 64 /* 页面大小(字节) */ #define EE_SIZE (32*1024) /* 总容量(字节) */ #define EE_ADDR_BYTES 1 /* 地址字节个数 */ extern unsigned char g_ucIsEEPROMBusy; void M24256_Init(void); uint8_t M24256_WriteByte(uint16_t _usAddress, uint8_t _ucByte); uint8_t M24256_ReadByte(uint16_t _usAddress); unsigned char M24256_ReadBlock(unsigned char *_pReadBuf, unsigned short _usSize, unsigned short _usAddress); unsigned char M24256_WriteBlock(unsigned char *_pWriteBuf, unsigned short _usSize, unsigned short _usAddress); void ee_Test(void); #endif /* __M24256_DRIVER_H__ */
原文地址:https://www.cnblogs.com/laoyou12138/p/11611079.html
- 用 RNN 训练语言模型生成文本
- 碎片化 | 第四阶段-38-Struts2登录session对象封装-视频
- LeetCode实战:子问题分析
- 5分钟构建一个自己的无人驾驶车
- 碎片化 | 第四阶段-39-Struts2中session对象梳理-视频
- 用深度神经网络处理NER命名实体识别问题
- 碎片化 | 第四阶段-40-Struts组件分类讲解-视频
- nginx location配置
- 碎片化 | 第四阶段-41-struts2字节流生成验证码-视频
- Python|模块,包,标准模板
- 人脸识别应用之“变脸”
- 碎片化 | 第四阶段-32-Struts2列表展示-视频
- Angularjs中UI Router超级详细的教程{{下}}
- 碎片化 | 第四阶段-33-Struts2-Spring整合环境概述讲解-视频
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 最简单入门深度学习
- 持续集成-Jenkins常用插件安装
- 小白学PyTorch | 15 TF2实现一个简单的服装分类任务
- 小白学PyTorch | 16 TF2读取图片的方法
- 小白学PyTorch | 17 TFrec文件的创建与读取
- 小白学PyTorch | 18 TF2构建自定义模型
- 扩展之Tensorflow2.0 | 19 TF2模型的存储与载入
- 扩展之Tensorflow2.0 | 20 TF2的eager模式与求导
- Django JSONField SQL注入漏洞(CVE-2019-14234)分析与影响
- 扩展之Tensorflow2.0 | 21 Keras的API详解(上)卷积、激活、初始化、正则
- 持续代码质量管理-SonarQube-7.3部署
- 攻击Scrapyd爬虫
- 【webpack】从vue-cli 2x 到 3x 迁移与实践
- 前端单元测试那些事
- 前端Nginx那些事