#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秒 } }