STM32模拟I2C程序
2016-06-27 10:43
344 查看
修改自cleanflight
/******************************************************************************* 测试平台:STM32F103ZET6最小系统 *******************************************************************************/ static void i2cDelay() { volatile int i = 7; while (i) i--; } // SCL高电平期间,SDA出现下降沿为起始信号 static bool i2cStart() { SDA_OUT; SCL_H; SDA_H; i2cDelay(); if (!sdaRead) // 如果SDA为低电平,则总线忙,退出 return false; SDA_L; if (sdaRead) // 如果SDA为高电平,则总线忙,退出 return false; SDA_L; return true; } // SCL高电平期间,SDA出现上升沿为停止信号 static void i2cStop(void) { SDA_OUT; SCL_L; SDA_L; i2cDelay(); // STOP:when CLK is high DATA from low to high SCL_H; SDA_H; i2cDelay(); } static void i2cAck(void) { SDA_OUT; SCL_L; i2cDelay(); SDA_L; i2cDelay(); SCL_H; i2cDelay(); SCL_L; } static void i2cNoAck(void) { SDA_OUT; SCL_L; i2cDelay(); SDA_H; i2cDelay(); SCL_H; i2cDelay(); SCL_L; } // SCL高电平期间,SDA电平被从设备拉低表示应答 static bool i2cWaitAck(void) { uint8_t errTimes = 0; SDA_IN; SDA_H; i2cDelay(); SCL_H; i2cDelay(); while (sdaRead) { if (errTimes++ > 20) { SCL_L; return false; } i2cDelay(); } SCL_L; return true; } // 发送数据,数据从高位到低位传输 static void i2cSendByte(uint8_t byte) { uint8_t i = 8; SDA_OUT; while (i--) { SCL_L; // 时钟信号为低电平期间,允许数据线电平变化 i2cDelay(); if (byte & 0x80) SDA_H; else SDA_L; byte <<= 1; i2cDelay(); SCL_H; i2cDelay(); } SCL_L; } static uint8_t i2cReceiveByte() { uint8_t i = 8; uint8_t byte = 0; SDA_IN; SDA_H; while (i--) { byte <<= 1; SCL_H; i2cDelay(); if (sdaRead) { byte |= 0x01; } SCL_L; i2cDelay(); } SCL_L; return byte; } void i2cInit() { GPIO_InitTypeDef GPIO_InitStructure; /* Enable GPIOB clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /* Configure GPIOB.6 & GPIOB.7 as open-drain output */ 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); } /** * 通过I2C总线写一字节数据 * @param[in] dev:设备I2C地址 * @param[in] reg:寄存器地址 * @param[in] data:要写入的数据 */ bool i2cWriteOneByte(uint8_t dev, uint8_t reg, uint8_t data) { if (!i2cStart()) return false; i2cSendByte(dev << 1); // 从机地址由高7位+读写位构成 if (!i2cWaitAck()) { i2cStop(); return false; } i2cSendByte(reg); i2cWaitAck(); i2cSendByte(data); i2cWaitAck(); return true; } /** * * @param[in] dev:设备I2C地址 * @param[in] reg:寄存器地址 * @param[in] len:字节数 * @param[in] data:待写入的数据 */ bool i2cWriteBytes(uint8_t dev, uint8_t reg, uint8_t len, uint8_t *data) { uint8_t i; if (!i2cStart()) return false; i2cSendByte(dev << 1); if (!i2cWaitAck()) { i2cStop(); return false; } i2cSendByte(dev); i2cWaitAck(); for (i = 0; i < len; i++) { i2cSendByte(data[i]); if (!i2cWaitAck()) { i2cStop(); return false; } } i2cStop(); return true; } /** * 从I2C设备中读取数据 * @param[in] dev:设备I2C地址 * @param[in] reg:寄存器地址 * @param[in] len:数据字节数 * @param[out] data:读出的数据 */ bool i2cReadBytes(uint8_t dev, uint8_t reg, uint8_t len, uint8_t *data) { if (!i2cStart()) return false; i2cSendByte(dev << 1); if (!i2cWaitAck()) { i2cStop(); return false; } i2cSendByte(reg); i2cWaitAck(); i2cStart(); i2cSendByte((dev << 1) | 0x01); // 器件地址+读命令 i2cWaitAck(); while (len) { *data = i2cReceiveByte(); if (len == 1) i2cNoAck(); // 最后一个字节不应答 else i2cAck(); data++; len--; } i2cStop(); return true; }
相关文章推荐
- lua编辑器
- iOS开发~CocoaPods使用详细说明
- thinkphp3.23整合phpexcel
- jQuery延迟加载(懒加载)插件 – jquery.lazyload.js
- 解决VC++2010&&VS2010无法调试&&调试无法进入断点&&无法命中断点的问题
- LeetCode—367. Valid Perfect Square
- 每天一个设计模式
- eclipse报错
- 分发糖果
- Android Studio Android UI控件学习笔记
- 网页上的“返回上一页”的几种实现代码
- POP Animation 和 layoutSubviews 的冲突
- js选择器全面解析
- Android应用程序的debug属性
- session过期时间
- 处理并发中奖概率方法
- Java swing使用皮肤后出现Component creation must be done on Event Dispatch Thread错误解决方法
- curl获取登录状态
- 程序员如何保持优秀
- 暑期二(A)(hdu2041)