Files
102_STC_I2C_SCAN/I2CM_refer/main.c

239 lines
5.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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为SDAP1.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秒
}
}