📄 main(i2c).c
字号:
/******************************************************************************************
文件名: main(I2c).c
文件功能: 程序主文件
创建人:
创建日期: 2007年5月13日
******************************************************************************************/
//---------------------------------------------------------------------------------------
// 头文件
//---------------------------------------------------------------------------------------
#include <ADuC845.h>
#include <stdio.h>
#include <math.h>
#include "main.h"
#include "intrins.h"
#define ADDR1 0x01
//----------------------------------------------------------------------------------------
// 全局变量定义
//----------------------------------------------------------------------------------------
bit Recieve_Mode = 0; // 数据接收模式标志位(0:接收命令字;1:接收数据)
bit success = 0; // 操作成功标志位
BYTE Command_Buffer[2]; // 命令字缓存区
BYTE Data_Buffer[5]; // 数据缓存区
BYTE CRC_Buffer[2]; // 校验码缓存区
UINT N=0; // 一个采集周期内采集的次数
ULONG G; // 压力码值
BYTE D[6]; // 压力,温度缓冲区
//----------------------------------------------------------------------------------------
// 函数原型
//----------------------------------------------------------------------------------------
void AD_Adj (void); // AD校准函数
void Read_Command(void); // 读命令字函数
void UART_ISR(void); // 串口中断服务函数
void UART_Send(BYTE); // 向串口发送数据函数
void Make_Respond(BYTE); // 命令响应函数
void Start_Collect(void); // 开始采集函数
void Stop_Collect(void); // 停止采集函数
void Send_Data(void); // 发送数据函数
void Self_Check(void); // 自检函数
void CRC_Init(void); // 校验码初始化函数
void ModBus_CRC(BYTE); // 校验码计算函数
void Delay(void); // 延时
void LM92_RD(void); // 读取LM92数据函数
void I2C_Write(BYTE); // 向I2C总线写数据函数
BYTE I2C_Read(void); // 从I2C总线读数据函数
void I2C_Start(void); // I2C起始函数
void I2C_Stop(void); // I2C停止函数
void I2C_ACK(void); // I2C确认函数
void I2C_NACK(void); // I2C非确认函数
BYTE I2C_RACK(void); // I2C接收确认信号函数
void I2C_NOP(void); // 延时函数
extern void UART_Send(BYTE);
//----------------------------------------------------------------------------------------
// 主函数
//----------------------------------------------------------------------------------------
void main(void)
{ BYTE m=0;
ICON=0x0B; // 选择激励电流源,400uA,由IEXC1输出
AD_Adj(); // AD校准
T3CON = 0x83; // 9600 Baud rate
T3FD = 0x12;
SCON = 0xC4; // 方式2,REN=1,SM2=1,TB8=0,RB8=1
while(!RI); // 等待上位机发送校验信号AA
RI=0;
if(SBUF==0xAA);
do{ // 接收到AA后回发11
SBUF=0x11;
}while(!TI);
TI=0;
ES=1; // 允许串口中断
EA=1; // 开启总中断
}
//----------------------------------------------------------------------------------------
// AD校准函数
//----------------------------------------------------------------------------------------
void AD_Adj (void)
{
SF=0xFF; // 设置为最大值
ADC0CON1=0x07; // 主ADC选用双极性方式,2.56V输入范围
ADC0CON2=0x4A; // 主ADC选用外部参考电源通过REFIN+/-引脚输入
ADCMODE=0x6E; // 60Hz,主ADC使能,非斩波模式,内部零点校准
CAL=0;
while(RDY0)
{
GN0L=ADC0L; // 保存主ADC内部零点的校准系数(偏移系数)
GN0M=ADC0M;
GN0H=ADC0H;
};
ADCMODE=0x6F;
CAL=0;
while(RDY0)
{
OF0L=ADC0L;
OF0M=ADC0M;
OF0H=ADC0H;
};
ADCMODE=0x6E; // 第二次主ADC零点校准
CAL=0;
while(RDY0)
{
GN0L=ADC0L;
GN0M=ADC0M;
GN0H=ADC0H;
};
}
//----------------------------------------------------------------------------------------
// 串口中断服务函数
//----------------------------------------------------------------------------------------
void UART_ISR(void) interrupt 8
{
if(SBUF==ADDR1)
{
SM2=0; // 准备接收、发送数据
RI=0;
do{
Command_Buffer[0]=SBUF;
}while(!RI);
RI=0;
Read_Command();
}
}
//----------------------------------------------------------------------------------------
// 执行命令函数
//----------------------------------------------------------------------------------------
void Read_Command(void) // 判断命令类型并散转执行
{
switch(Command_Buffer[0])
{
case START:
if(Command_Buffer[1] == START) // 响应开始采集命令
{
Make_Respond(0x44);
Start_Collect();
}
break;
case STOP:
if(Command_Buffer[1] == STOP) // 响应停止采集命令
{
Make_Respond(0x55);
Stop_Collect();
}
break;
case SEND:
if(Command_Buffer[1] == SEND) // 响应传输数据命令
{
Make_Respond(0x66);
Send_Data();
}
break;
case CHECK:
if(Command_Buffer[1] == CHECK) // 响应自检命令
{
Make_Respond(0x77);
Self_Check();
}
break;
default:
break;
}
}
//---------------------------------------------------------------------------------------
// 命令响应函数
//---------------------------------------------------------------------------------------
void Make_Respond(BYTE m1) // 发送命令ID并等待响应
{
do{
SBUF=m1;
while(TI);
TI=0;
while(RI);
RI=0;
}while(SBUF!=0xBB);
}
//---------------------------------------------------------------------------------------
// 开始采集函数
//---------------------------------------------------------------------------------------
void Start_Collect(void)
{
SF=0xFF;
ADC0CON1=0x07; // 主ADC选用单极性方式,2.56V输入范围
ADC0CON2=0x4A; // 主ADC选用外部参考电压REFIN+/-引脚输入
ADCMODE=0x63; // 60Hz抑制,主ADC使能,连续转换
TIMECON=0x39; // 设置TIC为24小时,秒寄存器输出
INTVAL=0x0A; // 设置每10秒中断一次,10秒到时产生中断,求出平均值
ET1=1; // 允许TIC中断
while(RDY0)
{
RDY0=0;
G+=ADC0H*65536+ADC0M*256+ADC0L;
LM92_RD();
N++;
}
}
//---------------------------------------------------------------------------------------
// 定时器中断执行求平均数函数
//---------------------------------------------------------------------------------------
void TIME_ISR(void) interrupt 10 using 1
{
ULONG R;
R=G/N;
N=0;
}
//---------------------------------------------------------------------------------------
// 停止采集函数
//---------------------------------------------------------------------------------------
void Stop_Collect(void)
{
}
//---------------------------------------------------------------------------------------
// 发送数据函数
//---------------------------------------------------------------------------------------
void Send_Data(void)
{ UINT i;
do{ // 联络
SBUF=0xDD;
while(TI);
TI=0;
while(RI);
RI=0;
}while(SBUF!=0xEE);
for(i=0;i<6;i++) // 发送温度、压力数据
{
SBUF=D[i];
while(!TI);
TI=0;
}
}
//----------------------------------------------------------------------------------------
// 自检函数
//----------------------------------------------------------------------------------------
void Self_Check(void)
{
// 检测数据电压
// 检测恒流源
// 检测参考电压
// 通信校验
}
//-----------------------------------------------------------------------------------------
// 读取LM92数据函数
//-----------------------------------------------------------------------------------------
void LM92_RD(void)
{
BYTE i;
MDE = 1;
MDO = 1;
MCO = 1;
I2C_Start();
I2C_NOP();
I2C_Write(0x91);
//MDE = 0;
for(i=0;i<100;i++) I2C_NOP();
UART_Send(I2C_RACK());
I2C_NOP();
Temp_Buffer[0] = I2C_Read();
I2C_ACK();
Temp_Buffer[1] = I2C_Read();
I2C_NACK();
I2C_Stop();
}
//----------------------------------------------------------------------------------------
// 向串口发送数据函数
//----------------------------------------------------------------------------------------
void UART_Send(BYTE byte_send)
{
ES = 0;
SBUF = byte_send;
while(!TI);
TI = 0;
ES = 1;
}
//-----------------------------------------------------------------------------------------
// 向I2C总线写数据函数
//-----------------------------------------------------------------------------------------
void I2C_Write(BYTE I2C_Data)
{
BYTE i;
//MDE = 1;
I2C_NOP();
for(i=0;i<8;i++)
{
SCK = 0;
I2C_NOP();
if(I2C_Data & 0x080) SDA = 1;
else SDA = 0;
I2C_Data = I2C_Data << 1;
I2C_NOP();
SCK = 1;
I2C_NOP();
}
SCK = 0;
I2C_NOP();
}
//-----------------------------------------------------------------------------------------
// 从I2C总线读数据函数
//-----------------------------------------------------------------------------------------
BYTE I2C_Read(void)
{
BYTE i,I2C_Data = 0;
//MDE = 0;
SCK = 0;
I2C_NOP();
SDA = 1;
for(i=0;i<8;i++)
{
SCK = 0;
I2C_NOP();
SCK = 1;
I2C_NOP();
if(SDA) I2C_Data ++;
I2C_Data = I2C_Data << 1;
}
SCK = 0;
I2C_NOP();
return(I2C_Data);
}
//-----------------------------------------------------------------------------------------
// I2C起始函数
//-----------------------------------------------------------------------------------------
void I2C_Start(void)
{
//MDE = 1; // 发送状态
I2C_NOP();
SCK = 0;
I2C_NOP();
SDA = 1; // SDA = 1
I2C_NOP();
SCK = 1; // SCL = 1
I2C_NOP();
SDA = 0; // SDA = 0
I2C_NOP();
SCK = 0;
I2C_NOP();
}
//-----------------------------------------------------------------------------------------
// I2C停止函数
//-----------------------------------------------------------------------------------------
void I2C_Stop(void)
{
//MDE = 1;
I2C_NOP();
SCK = 0;
I2C_NOP();
SDA = 0; // SDA = 0
I2C_NOP();
SCK = 1; // SCL = 1
I2C_NOP();
SDA = 1;
I2C_NOP();
SCK = 0;
I2C_NOP();
}
//-----------------------------------------------------------------------------------------
// I2C确认函数
//-----------------------------------------------------------------------------------------
void I2C_ACK(void)
{
//MDE = 1;
I2C_NOP();
SCK = 0;
I2C_NOP();
SDA = 0;
I2C_NOP();
SCK = 1;
I2C_NOP();
SCK = 0;
I2C_NOP();
}
//-----------------------------------------------------------------------------------------
// I2C非确认函数
//-----------------------------------------------------------------------------------------
void I2C_NACK(void)
{
//MDE = 1;
I2C_NOP();
SCK = 0;
I2C_NOP();
SDA = 1;
I2C_NOP();
SCK = 1;
I2C_NOP();
SCK = 0;
I2C_NOP();
}
//-----------------------------------------------------------------------------------------
// I2C接收确认信号函数
//-----------------------------------------------------------------------------------------
BYTE I2C_RACK(void)
{
BYTE i;
//MDE = 0;
I2C_NOP();
SCK = 0;
I2C_NOP();
SDA = 1;
I2C_NOP();
SCK = 1;
I2C_NOP();
if(SDA) i = 0xEE;
else i = 0xAA;
SCK = 0;
I2C_NOP();
return(i);
}
//-----------------------------------------------------------------------------------------
// 延时函数
//-----------------------------------------------------------------------------------------
void I2C_NOP(void)
{
BYTE i;
for(i=0;i<32;i++);
}
//----------------------------------------------------------------------------------------
// 校验码初始化函数
//----------------------------------------------------------------------------------------
void CRC_Init(void)
{
CRC_Buffer[0] = 0xFF; // 校验码低字节
CRC_Buffer[1] = 0xFF; // 校验码高字节
}
//----------------------------------------------------------------------------------------
// 校验码计算函数
//----------------------------------------------------------------------------------------
void ModBus_CRC(BYTE Data_CRC)
{
BYTE i; UINT CRC;
CRC_Buffer[0] ^= Data_CRC;
for(i=0;i<8;i++)
{
Data_CRC = CRC_Buffer[0] & 0x01;
CRC = ((UINT)(CRC_Buffer[1]) << 8) + CRC_Buffer[0];
CRC = CRC >> 1;
CRC_Buffer[1] = ((BYTE)(CRC >> 8)) & 0x7F;
CRC_Buffer[0] = (BYTE)(CRC);
if(Data_CRC == 0x01)
{
CRC_Buffer[1] ^= 0xA0;
CRC_Buffer[0] ^= 0x01;
}
}
}
//----------------------------------------------------------------------------------------
// 延时函数
//----------------------------------------------------------------------------------------
void Delay(void)
{
BYTE i,j;
for(i=0;i<0xFF;i++)
for(j=0;j<0xFF;j++);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -