当设计中使用I2C的数量多于1个时,其底层I2C的代码逻辑都是一样的,只有IO口变了,为此还要复制粘贴、修改IO,不仅费时,而且还浪费片内资源,因此可以使用指针来重复执行IIC底层代码,实现一个代码,多个IO使用。
#ifndef __Stm32f30x_SMLT_I2C_H
#define __Stm32f30x_SMLT_I2C_H
//========================= Include ===============================================================
#include "stm32f30x.h"
//========================= Variable ==============================================================
typedef struct
{
GPIO_TypeDef* I2C_GPIO;
uint32_t SDA_SBIT;
uint32_t SDA_RBIT;
uint32_t SCL_SBIT;
uint32_t SCL_RBIT;
uint32_t SDA_MODER;
uint32_t SDA_MODER_0;
uint32_t SDA_MODER_1;
}I2C_Struct;
extern I2C_Struct S_I2C_IO[2];//------------------------------------- 需修改
//(想要3个的话,数组添加,下面的define也要添加,初始化函数S_I2C_Init中也要添加)
//========================= I2C1_Define ================================================================
//--------------------------SDA-------------------------------------- 需修改
#define S_I2C1_SDA_GPIO GPIOB
#define S_I2C1_SDA_BIT 9
//--------------------------SCL-------------------------------------- 需修改
#define S_I2C1_SCL_GPIO GPIOB
#define S_I2C1_SCL_BIT 8
//还需配置结构体初始化函数 S_I2C_Init
//========================= I2C2_Define ================================================================
//--------------------------SDA-------------------------------------- 需修改
#define S_I2C2_SDA_GPIO GPIOE
#define S_I2C2_SDA_BIT 1
//--------------------------SCL-------------------------------------- 需修改
#define S_I2C2_SCL_GPIO GPIOE
#define S_I2C2_SCL_BIT 0
//还需配置结构体初始化函数 S_I2C_Init
// //========================= I2Cx_Define ================================================================
// //--------------------------SDA-------------------------------------- 需修改
// #define S_I2Cx_SDA_GPIO GPIOx
// #define S_I2Cx_SDA_BIT x
// //--------------------------SCL-------------------------------------- 需修改
// #define S_I2Cx_SCL_GPIO GPIOx
// #define S_I2Cx_SCL_BIT x
// //添加在此添加
//========================= Function ==============================================================
void S_I2C_Init(void);//--------------------------------------------- 需修改
void S_I2C_Start(I2C_Struct I2C_temp);
void S_I2C_Stop(I2C_Struct I2C_temp);
uint8_t S_I2C_SendByte(I2C_Struct I2C_temp, uint8_t byte);
uint8_t S_I2C_ReceiveByte(I2C_Struct I2C_temp, uint8_t nack);
uint8_t S_I2C_WriteRegister(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t data);
uint8_t S_I2C_ReadRegister(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t amount, uint8_t* data, uint8_t typ);
uint8_t S_I2C_PointerRead(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t amount, uint8_t* data, uint8_t typ);
//========================= Define ================================================================
//通过宏定义将IO结构体直接放入基础函数中
//-------------------------- I2C1 -----------------------------------
#define S_I2C1_Start() S_I2C_Start(S_I2C_IO[0])
#define S_I2C1_Stop() S_I2C_Stop(S_I2C_IO[0])
#define S_I2C1_SendByte(byte) S_I2C_SendByte(S_I2C_IO[0], byte)
#define S_I2C1_ReceiveByte(nack) S_I2C_ReceiveByte(S_I2C_IO[0], nack)
#define S_I2C1_WriteRegister(addr, regAddr, data) S_I2C_WriteRegister(S_I2C_IO[0], addr, regAddr, data)
#define S_I2C1_ReadRegister(addr, regAddr, amount, data, typ) S_I2C_ReadRegister(S_I2C_IO[0], addr, regAddr, amount, data, typ)
#define S_I2C1_PointerRead(addr, regAddr, amount, data, typ) S_I2C_PointerRead(S_I2C_IO[0], addr, regAddr, amount, data, typ)
//-------------------------- I2C2 -----------------------------------
#define S_I2C2_Start() S_I2C_Start(S_I2C_IO[1])
#define S_I2C2_Stop() S_I2C_Stop(S_I2C_IO[1])
#define S_I2C2_SendByte(byte) S_I2C_SendByte(S_I2C_IO[1], byte)
#define S_I2C2_ReceiveByte(nack) S_I2C_ReceiveByte(S_I2C_IO[1], nack)
#define S_I2C2_WriteRegister(addr, regAddr, data) S_I2C_WriteRegister(S_I2C_IO[1], addr, regAddr, data)
#define S_I2C2_ReadRegister(addr, regAddr, amount, data, typ) S_I2C_ReadRegister(S_I2C_IO[1], addr, regAddr, amount, data, typ)
#define S_I2C2_PointerRead(addr, regAddr, amount, data, typ) S_I2C_PointerRead(S_I2C_IO[1], addr, regAddr, amount, data, typ)
//-------------------------- Another --------------------------------
#define ACK 0
#define NACK 1
#define FAILED 0
#define SUCCEED 1
//=================================================================================================
#endif
#include "Stm32f30x_SMLT_I2C.h"
I2C_Struct S_I2C_IO[2];//IO口结构体,通过.h文件定义使用的引脚
/**
* @description: I2C结构体IO初始化
* @param {I2C_Struct*} I2C_temp I2C的IO结构体
* @param {uint8_t} SDA_BIT I2C SDA引脚号(1~16)
* @param {uint8_t} SCL_BIT I2C SCL引脚号(1~16)
* @return {*}
*/
void S_I2C_IO_Init(I2C_Struct* I2C_temp, GPIO_TypeDef* I2C_GPIO, uint8_t SDA_BIT, uint8_t SCL_BIT)
{
I2C_temp->I2C_GPIO = I2C_GPIO;
I2C_temp->SDA_SBIT = (SBIT0 << SDA_BIT);
I2C_temp->SDA_RBIT = (RBIT0 << SDA_BIT);
I2C_temp->SCL_SBIT = (SBIT0 << SCL_BIT);
I2C_temp->SCL_RBIT = (RBIT0 << SCL_BIT);
I2C_temp->SDA_MODER = 0x03 << (SDA_BIT << 1);
I2C_temp->SDA_MODER_0 = 0x01 << (SDA_BIT << 1);
I2C_temp->SDA_MODER_1 = 0x02 << (SDA_BIT << 1);
}
/**
* @description: I2C结构体总初始化,将计算的各个变量存入结构体中
* @param {*}
* @return {*}
*/
void S_I2C_Init(void)
{
S_I2C_IO_Init(&S_I2C_IO[0], S_I2C1_SDA_GPIO, S_I2C1_SDA_BIT, S_I2C1_SCL_BIT);
S_I2C_IO_Init(&S_I2C_IO[1], S_I2C2_SDA_GPIO, S_I2C2_SDA_BIT, S_I2C2_SCL_BIT);
// S_I2C_IO_Init(&S_I2C_IO[x], S_I2Cx_SDA_GPIO, S_I2Cx_SDA_BIT, S_I2Cx_SCL_BIT); //添加在此添加
}
/**
* @description: I2C时钟延时,调整波特率
* @param {*}
* @return {*}
*/
void Delay(void)
{
for (uint8_t i = 0; i < 0x10; i++)
{
/* code */
}
}
/**
* @description: 产生起始信号
* @param {I2C_Struct} I2C_temp I2C_IO结构体
* @return {*}
*/
void S_I2C_Start(I2C_Struct I2C_temp)
{
I2C_temp.I2C_GPIO->MODER |= I2C_temp.SDA_MODER_0;
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SDA_SBIT;
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SCL_SBIT;
Delay();
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SDA_RBIT;
Delay();
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SCL_RBIT;
Delay();
}
/**
* @description: 产生停止信号
* @param {I2C_Struct} I2C_temp
* @return {*}
*/
void S_I2C_Stop(I2C_Struct I2C_temp)
{
I2C_temp.I2C_GPIO->MODER |= I2C_temp.SDA_MODER_0;
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SCL_RBIT;
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SDA_RBIT;
Delay();
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SCL_SBIT;
Delay();
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SDA_SBIT;
Delay();
}
/**
* @description: 发送一个字节数据
* @param {I2C_Struct} I2C_temp I2C_IO结构体
* @param {uint8_t} byte 数据
* @return {uint8_t} NACK
* ACK
*/
uint8_t S_I2C_SendByte(I2C_Struct I2C_temp, uint8_t byte)
{
uint8_t temp = 0x00;
for(uint8_t i = 0x80; i; i >>= 1)
{
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SCL_RBIT;
if(byte & i)
{
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SDA_SBIT;
}
else
{
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SDA_RBIT;
}
Delay();
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SCL_SBIT;
Delay();
}
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SCL_RBIT;
I2C_temp.I2C_GPIO->MODER &= ~I2C_temp.SDA_MODER;
Delay();
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SCL_SBIT;
if(I2C_temp.I2C_GPIO -> IDR & I2C_temp.SDA_SBIT)
{
temp = NACK;
}
else
{
temp = ACK;
}
Delay();
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SDA_RBIT;
I2C_temp.I2C_GPIO->MODER |= I2C_temp.SDA_MODER_0;
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SCL_RBIT;
Delay();
return temp;
}
/**
* @description: 接收一个字节数据
* @param {I2C_Struct} I2C_temp I2C_IO结构体
* @param {uint8_t} nack 接收后结束要发送的应答信号
* NACK
* ACK
* @return {uint8_t} 接收到的字节
*/
uint8_t S_I2C_ReceiveByte(I2C_Struct I2C_temp, uint8_t nack)
{
uint8_t byte = 0x00;
I2C_temp.I2C_GPIO->MODER &= ~I2C_temp.SDA_MODER;
for (uint8_t i = 8; i; i--)
{
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SCL_RBIT;
Delay();
byte <<= 1;
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SCL_SBIT;
if(I2C_temp.I2C_GPIO -> IDR & I2C_temp.SDA_SBIT)
{
byte |= 0x01;
}
Delay();
}
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SCL_RBIT;
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SDA_RBIT;
I2C_temp.I2C_GPIO->MODER |= I2C_temp.SDA_MODER_0;
if(nack)
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SDA_SBIT;
else
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SDA_RBIT;
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SCL_RBIT;
Delay();
I2C_temp.I2C_GPIO->BSRR |= I2C_temp.SCL_SBIT;
Delay();
return byte;
}
/**
* @description: 写一个字节的寄存器
* @param {I2C_Struct} I2C_temp I2C_IO结构体
* @param {uint8_t} addr 器件地址(0x00~0x7f)
* @param {uint8_t} regAddr 寄存器地址(0x00~0xff)
* @param {uint8_t} data 数据
* @return {uint8_t} FAILED 失败
* SUCCEED 成功
*/
uint8_t S_I2C_WriteRegister(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t data)
{
addr <<= 1;
S_I2C_Start(I2C_temp);
if(S_I2C_SendByte(I2C_temp, addr) == NACK)
{
S_I2C_Stop(I2C_temp);
return FAILED;
}
if(S_I2C_SendByte(I2C_temp, regAddr) == NACK)
{
S_I2C_Stop(I2C_temp);
return FAILED;
}
if(S_I2C_SendByte(I2C_temp, data) == NACK)
{
S_I2C_Stop(I2C_temp);
return FAILED;
}
S_I2C_Stop(I2C_temp);
return SUCCEED;
}
/**
* @description: 读取器件,读取格式:器件读-寄存器地址-读取数据
* @param {I2C_Struct} I2C_temp I2C_IO结构体
* @param {uint8_t} addr 器件地址(0x00~0x7f)
* @param {uint8_t} regAddr 寄存器地址(0x00~0xff)
* @param {uint8_t} amount 读取数据数量(0x00~0xff)
* @param {uint8_t*} data 返回数据指针
* @param {uint8_t} typ 数据指针类型
* ARRAY
* STRUCT
* @return {*} FAILD 失败
* SUCCEED 成功
*/
uint8_t S_I2C_ReadRegister(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t amount, uint8_t* data, uint8_t typ)
{
S_I2C_Start(I2C_temp);
addr = (addr << 1) | 0x01;
if(S_I2C_SendByte(I2C_temp, addr) == NACK)
{
S_I2C_Stop(I2C_temp);
return FAILED;
}
if(S_I2C_SendByte(I2C_temp, regAddr) == NACK)
{
S_I2C_Stop(I2C_temp);
return FAILED;
}
for(amount -= 1;amount;amount --)
{
*data = S_I2C_ReceiveByte(I2C_temp, ACK);
if(typ == ARRAY)
data ++;
else
data --;
}
*data = S_I2C_ReceiveByte(I2C_temp, NACK);
S_I2C_Stop(I2C_temp);
return SUCCEED;
}
/**
* @description: 读取器件,读取格式:器件写-寄存器地址-器件读-读取数据
* @param {I2C_Struct} I2C_temp I2C_IO结构体
* @param {uint8_t} addr 器件地址(0x00~0x7f)
* @param {uint8_t} regAddr 寄存器地址(0x00~0xff)
* @param {uint8_t} amount 读取数据数量(0x00~0xff)
* @param {uint8_t*} data 返回数据指针
* @param {uint8_t} typ 数据指针类型
* ARRAY
* STRUCT
* @return {uint8_t} FAILD 失败
* SUCCEED 成功
*/
uint8_t S_I2C_PointerRead(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t amount, uint8_t* data, uint8_t typ)
{
addr <<= 1;
S_I2C_Start(I2C_temp);
if(S_I2C_SendByte(I2C_temp, addr) == NACK)
{
S_I2C_Stop(I2C_temp);
return FAILED;
}
if(S_I2C_SendByte(I2C_temp, regAddr) == NACK)
{
S_I2C_Stop(I2C_temp);
return FAILED;
}
S_I2C_Stop(I2C_temp);
addr |= 0x01;
S_I2C_Start(I2C_temp);
if(S_I2C_SendByte(I2C_temp, addr) == NACK) //NACK
{
S_I2C_Stop(I2C_temp);
return FAILED;
}
for(amount -= 1;amount;amount --)
{
*data = S_I2C_ReceiveByte(I2C_temp, ACK);
if(typ == ARRAY)
data ++;
else
data --;
}
*data = S_I2C_ReceiveByte(I2C_temp, NACK);
S_I2C_Stop(I2C_temp);
return SUCCEED;
}
主要目的 a. 掌握获取 GridPanel 当前行的各个字段值的方法 b. 掌握如何将前台数...
如果你很在意你的终端的外观的话,一个跨 shell 的提示符可以让你轻松地定制和配...
例如: 我们在百度中搜索 尊托云数,则网址后面的参数就是 http://www.baidu.com/...
发现每个编辑实例都可以加载不同的css样式表,而且其样式不继承 页面的css。 于...
我之前写过一个简易版的自动+手动轮播图: 简易轮播图 但是这个轮播图在切换的时...
关于我的SWFObject V1.5的使用过程,以 上篇 中的介绍暂时告一段落了,下面我将...
Mysql数据库五——mysql事务及引擎 一、事务 1、事务的概念 2、事务的ACID特点 ...
接着昨天的,如果forEach中的items类型是map或者Collection类型的,怎样使用增强...
本文实例为大家分享了js实现电灯开关效果的具体代码,供大家参考,具体内容如下 ...
Asp 解析 XML并分页显示,示例源码如下: 复制代码 代码如下: !DOCTYPE html PUB...