239 lines
5.1 KiB
C
239 lines
5.1 KiB
C
|
|
#include "reg51.h"
|
|||
|
|
#include "intrins.h"
|
|||
|
|
|
|||
|
|
// 定义I2C相关寄存器
|
|||
|
|
sfr P_SW2 = 0xba;
|
|||
|
|
#define I2CCFG (*(unsigned char volatile xdata *)0xfe80)
|
|||
|
|
#define I2CMSCR (*(unsigned char volatile xdata *)0xfe81)
|
|||
|
|
#define I2CMSST (*(unsigned char volatile xdata *)0xfe82)
|
|||
|
|
#define I2CSLCR (*(unsigned char volatile xdata *)0xfe83)
|
|||
|
|
#define I2CSLST (*(unsigned char volatile xdata *)0xfe84)
|
|||
|
|
#define I2CSLADR (*(unsigned char volatile xdata *)0xfe85)
|
|||
|
|
#define I2CTXD (*(unsigned char volatile xdata *)0xfe86)
|
|||
|
|
#define I2CRXD (*(unsigned char volatile xdata *)0xfe87)
|
|||
|
|
|
|||
|
|
// 定义端口模式寄存器
|
|||
|
|
sfr P1M1 = 0x91;
|
|||
|
|
sfr P1M0 = 0x92;
|
|||
|
|
|
|||
|
|
// 定义I2C引脚
|
|||
|
|
sbit SDA = P1^4;
|
|||
|
|
sbit SCL = P1^5;
|
|||
|
|
|
|||
|
|
// 定义LED引脚
|
|||
|
|
sbit LED = P1^2;
|
|||
|
|
|
|||
|
|
// 全局变量
|
|||
|
|
bit busy; // I2C忙碌标志
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief I2C中断服务函数
|
|||
|
|
* @note 中断号24,用于处理I2C通信完成事件
|
|||
|
|
*/
|
|||
|
|
void I2C_Isr() interrupt 24
|
|||
|
|
{
|
|||
|
|
_push_(P_SW2);
|
|||
|
|
P_SW2 |= 0x80; // 访问扩展寄存器
|
|||
|
|
if (I2CMSST & 0x40) // 检查中断标志
|
|||
|
|
{
|
|||
|
|
I2CMSST &= ~0x40; // 清除中断标志
|
|||
|
|
busy = 0; // 清除忙碌标志
|
|||
|
|
}
|
|||
|
|
_pop_(P_SW2);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 等待I2C操作完成
|
|||
|
|
*/
|
|||
|
|
void I2C_Wait()
|
|||
|
|
{
|
|||
|
|
while(!(I2CMSST & 0x40));
|
|||
|
|
I2CMSST &= ~0x40; // 清除中断标志
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 发送I2C起始信号
|
|||
|
|
*/
|
|||
|
|
void I2C_Start()
|
|||
|
|
{
|
|||
|
|
busy = 1;
|
|||
|
|
I2CMSCR = 0x81; // 发送START命令
|
|||
|
|
while (busy); // 等待操作完成
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 发送I2C数据
|
|||
|
|
* @param dat 要发送的数据
|
|||
|
|
*/
|
|||
|
|
void I2C_SendData(unsigned char dat)
|
|||
|
|
{
|
|||
|
|
I2CTXD = dat; // 写数据到数据缓冲区
|
|||
|
|
busy = 1;
|
|||
|
|
I2CMSCR = 0x82; // 发送SEND命令
|
|||
|
|
while (busy); // 等待操作完成
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 接收I2C应答信号
|
|||
|
|
*/
|
|||
|
|
void I2C_RecvACK()
|
|||
|
|
{
|
|||
|
|
busy = 1;
|
|||
|
|
I2CMSCR = 0x83; // 发送读ACK命令
|
|||
|
|
while (busy); // 等待操作完成
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
char I2C_RecvData()
|
|||
|
|
{
|
|||
|
|
busy = 1;
|
|||
|
|
I2CMSCR = 0x84; // 发送读数据命令
|
|||
|
|
while (busy); // 等待操作完成
|
|||
|
|
return I2CRXD; // 返回接收数据
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void I2C_SendACK()
|
|||
|
|
{
|
|||
|
|
I2CMSST = 0x00; //设置ACK信号
|
|||
|
|
I2CMSCR = 0x05; // 发送ACK命令
|
|||
|
|
I2C_Wait(); // 等待操作完成
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void I2C_SendNAK()
|
|||
|
|
{
|
|||
|
|
I2CMSST = 0x01; //设置NACK信号
|
|||
|
|
I2CMSCR = 0x05; // 发送NACK命令
|
|||
|
|
I2C_Wait(); // 等待操作完成
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 发送I2C停止信号
|
|||
|
|
*/
|
|||
|
|
void I2C_Stop()
|
|||
|
|
{
|
|||
|
|
I2CMSCR = 0x06; // 发送STOP命令
|
|||
|
|
I2C_Wait(); // 等待操作完成
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// /**
|
|||
|
|
// * @brief 延时函数
|
|||
|
|
// * @param ms 延时毫秒数
|
|||
|
|
// */
|
|||
|
|
// void Delay_ms(unsigned int ms) //@24.000MHz
|
|||
|
|
// {
|
|||
|
|
// unsigned int i, j;
|
|||
|
|
// for (i = 0; i < ms; i++)
|
|||
|
|
// {
|
|||
|
|
// for (j = 0; j < 3500; j++);
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
// void Delay10us(void) //@24.000MHz
|
|||
|
|
// {
|
|||
|
|
// unsigned char data i;
|
|||
|
|
|
|||
|
|
// i = 78;
|
|||
|
|
// while (--i);
|
|||
|
|
// }
|
|||
|
|
/**
|
|||
|
|
* @brief 延时函数
|
|||
|
|
* @param ms 延时毫秒数
|
|||
|
|
*/
|
|||
|
|
void Delay_ms(unsigned int ms) //@11.0592MHz
|
|||
|
|
{
|
|||
|
|
unsigned int i, j;
|
|||
|
|
for (i = 0; i < ms; i++)
|
|||
|
|
{
|
|||
|
|
for (j = 0; j < 1550; j++);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
void Delay10us(void) //@11.0592MHz
|
|||
|
|
{
|
|||
|
|
unsigned char data i;
|
|||
|
|
|
|||
|
|
i = 35;
|
|||
|
|
while (--i);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief I2C初始化函数
|
|||
|
|
* @note 配置P1.4为SDA,P1.5为SCL,设置100k通信速率
|
|||
|
|
*/
|
|||
|
|
void I2C_Init()
|
|||
|
|
{
|
|||
|
|
// 配置端口模式
|
|||
|
|
P1M0 = 0x04; // P1.2设置为推挽输出,P1.4和P1.5保持准双向口
|
|||
|
|
P1M1 = 0x00;
|
|||
|
|
|
|||
|
|
// 访问扩展寄存器
|
|||
|
|
P_SW2 = 0x80;
|
|||
|
|
|
|||
|
|
// 配置I2C通信速率为50kHz
|
|||
|
|
// 系统时钟11.059MHz
|
|||
|
|
// MSSPEED = (1105900/100000/2 -4)/2 = 25
|
|||
|
|
I2CCFG = 0xe0 | 0x10; // 0xe0使能I2C主机模式,0x10设置MSSPEED=25
|
|||
|
|
|
|||
|
|
// 初始化I2C状态
|
|||
|
|
I2CMSST = 0x00;
|
|||
|
|
|
|||
|
|
// 启用全局中断·
|
|||
|
|
EA = 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 向指定设备的指定寄存器发送I2C数据
|
|||
|
|
* @param devAddr 设备地址
|
|||
|
|
* @param regAddr 寄存器地址
|
|||
|
|
* @param dat 要发送的数据
|
|||
|
|
*/
|
|||
|
|
void I2C_SendToRegister(unsigned char devAddr, unsigned char regAddr, unsigned char dat)
|
|||
|
|
{
|
|||
|
|
I2C_Start(); // 发送起始信号
|
|||
|
|
I2C_SendData(devAddr); // 发送设备地址+写命令
|
|||
|
|
I2C_RecvACK(); // 接收应答
|
|||
|
|
I2C_SendData(regAddr); // 发送寄存器地址
|
|||
|
|
I2C_RecvACK(); // 接收应答
|
|||
|
|
I2C_SendData(dat); // 发送数据
|
|||
|
|
I2C_RecvACK(); // 接收应答
|
|||
|
|
I2C_Stop(); // 发送停止信号
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 主函数
|
|||
|
|
*/
|
|||
|
|
void main()
|
|||
|
|
{
|
|||
|
|
// 初始化数据变量,用于0x96寄存器的数据递增
|
|||
|
|
unsigned char reg96_data = 0;
|
|||
|
|
// 初始化I2C
|
|||
|
|
I2C_Init();
|
|||
|
|
|
|||
|
|
// 点亮LED(保持常亮)
|
|||
|
|
LED = 0; // 推挽输出低电平点亮LED
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 主循环
|
|||
|
|
while (1)
|
|||
|
|
{
|
|||
|
|
// 向设备0x8A的三个不同寄存器发送数据
|
|||
|
|
// 发送到寄存器0x94,数据0x03
|
|||
|
|
I2C_SendToRegister(0x8A, 0x94, 0x03);
|
|||
|
|
Delay10us(); // 延时10us
|
|||
|
|
|
|||
|
|
// 发送到寄存器0x95,数据0x17
|
|||
|
|
I2C_SendToRegister(0x8A, 0x95, 0x17);
|
|||
|
|
Delay10us(); // 延时10us
|
|||
|
|
|
|||
|
|
// 发送到寄存器0x96,数据递增
|
|||
|
|
I2C_SendToRegister(0x8A, 0x96, reg96_data);
|
|||
|
|
|
|||
|
|
// 数据递增5,达到255后重置为0
|
|||
|
|
reg96_data += 5;
|
|||
|
|
if (reg96_data > 0xFF)
|
|||
|
|
{
|
|||
|
|
reg96_data = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Delay_ms(1000); // 延时1秒
|
|||
|
|
}
|
|||
|
|
}
|