📄 hardi2c.c
字号:
// 包含头文件
#include "hw_memmap.h"
#include "hw_types.h"
#include "hw_ints.h"
#include "hw_i2c.h"
#include "sysctl.h"
#include "gpio.h"
#include "i2c.h"
#include "UART_GetPut.H"
#include "stdio.h"
#include "interrupt.h"
#include "HardI2C.h"
// 定义I2C中断操作所用到的全局变量
unsigned char GucStat = STAT_IDLE; // I2C工作状态标志
unsigned char GucSLA = 0x00; // 主机从地址
unsigned char *GpucData = (void *)0; // 保存接收到的数据
unsigned char GucSize = 0x00; // 数据长度
// I2C主模块初始化
void I2CM_Init()
{
SysCtlClockSet(SYSCTL_SYSDIV_1 |
SYSCTL_USE_OSC |
SYSCTL_OSC_MAIN |
SYSCTL_XTAL_6MHZ); // 配置外部6MHz晶振作为CPU主频
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // 使能I2C管脚所在的GPIO
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C); // 使能I2C模块
GPIOPinTypeI2C(GPIO_PORTB_BASE, I2C_SCL|I2C_SDA); // I2C管脚配置
I2CMasterInit(I2C_MASTER_BASE, false); // I2C主模块初始化,100kbps速率
IntMasterEnable(); // 使能总中断
IntEnable(INT_I2C); // 使能I2C中断
I2CMasterIntEnable(I2C_MASTER_BASE); // 使能I2C主模块中断
}
// I2C主模块突发发送后突发接收(返回接收到的多个字节有效数据)
// {S | SLA+W | addr | Sr | SLA+R | data_1 | ... | data_n | P}
void I2CM_BurstSendReceive(unsigned char ucSLA, // 从机地址
unsigned char ucAddr, // 数据存储地址
unsigned char *pucData, // 保存接收到的数据
unsigned char ucSize) // 数据长度
{
GucStat = STAT_RECEIVE_START; // 初始化为起始接收状态
GucSLA = ucSLA;
GpucData = pucData;
GucSize = ucSize;
I2CMasterSlaveAddrSet(I2C_MASTER_BASE, // 设置SLA+W
ucSLA, // 该函数不执行任何I2C时序上的操作
false);
I2CMasterDataPut(I2C_MASTER_BASE, ucAddr); // 设置数据存储地址
// 该函数不执行任何I2C时序上的操作
I2CMasterControl(I2C_MASTER_BASE, // 启动I2C主模块突发发送
I2C_MASTER_CMD_BURST_SEND_START); // 总线动作:{S | SLA+W | addr}
while ( GucStat != STAT_IDLE ); // 等待I2C中断操作完毕
}
// I2C主模块中断服务函数
void I2C_ISR(void)
{
unsigned char ucTmp = 0x00; //临时变量
I2CMasterIntClear(I2C_MASTER_BASE); // 清除中断状态,重要!
switch ( GucStat ) // 判断当前运行状态
{
case STAT_IDLE: // 空闲状态
ucTmp = 0x00;
break;
case STAT_RECEIVE_START: // 接收起始状态
I2CMasterSlaveAddrSet(I2C_MASTER_BASE, // 设置SLA+R
GucSLA,
true);
if ( GucSize == 1 ) // 如果只接收1个字节的有效数据
{
I2CMasterControl(I2C_MASTER_BASE, // 重复起始,接收有效数据,停止
I2CM_CMD_PSR); // 总线动作 {Sr | SLA+R | data | P}
GucStat = STAT_RECEIVE_LAST; // 变成最后接收状态
}
else
{
I2CMasterControl(I2C_MASTER_BASE, // 先重复起始,再应答接收
I2C_MASTER_CMD_BURST_RECEIVE_START);
// 总线动作 {Sr | SLA+R | data_1}
GucStat = STAT_RECEIVE_CONT; // 变成继续接收状态
}
break;
case STAT_RECEIVE_CONT: // 继续接收状态
ucTmp = I2CMasterDataGet(I2C_MASTER_BASE); // 读取有效数据
*GpucData++ = ucTmp; // 保存有效数据
if ( --GucSize == 1 ) // 如果准备接收最后1个数据
{
I2CMasterControl(I2C_MASTER_BASE, // 接收后停止
I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
// 总线动作 {data_n | P}
GucStat = STAT_RECEIVE_LAST; // 变成最后接收状态
}
else
{
// 保持继续接收状态不变
}
break;
case STAT_RECEIVE_LAST: // 最后接收状态
ucTmp = I2CMasterDataGet(I2C_MASTER_BASE); // 读取最后1个有效数据
*GpucData++ = ucTmp; // 保存最后1个有效数据
GucStat = STAT_IDLE; // 变成空闲状态
break;
default:
break;
}
}
// 读取LM75A的温度值,并通过UART发送显示
void TmpDisp(void)
{
char TmpTab[8][4] =
{
"000",
"125",
"250",
"375",
"500",
"625",
"750",
"875"
};
unsigned char ucData[2];
char cBuf[20];
short sTmp;
I2CM_BurstSendReceive(SLA_LM75A, LM75A_REG_TMP, ucData, 2);
sTmp = ucData[0];
sTmp <<= 8;
sTmp |= ucData[1] & 0xE0;
if ( sTmp < 0 )
{
sTmp = -sTmp;
UART_Puts("-");
}
sprintf(cBuf, "%d", (sTmp / 256));
UART_Puts(cBuf);
UART_Puts(".");
UART_Puts(TmpTab[(sTmp >> 5) & 0x07]);
UART_Puts("\r\n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -