📄 ad_cy.c
字号:
/* --- AD采样程序------------------------------------------------------------ */
/* --- 史继前 设计 2009.02.20 V1.2 ------------------------------------------ */
/* --- 程序代码版本:V1.2 -------------------------------------------------- */
/* --- 演示 在AD采样电流值的精确性------------------------------------------- */
/* --- Mobile: 15999617642 -------------------------------------------------- */
/* --- 文档说明请查阅测试文档V1.2-------------------------------------------- */
#include<reg52.h>
#define RELOAD 0xf3 //此为串口1,串口波特率重装数值。晶振:24M,12T模式,SMOD=0,
//串口波特率基准采用4800bps.
void AD_Iint(void); //AD初始化
void AD_Interrupt(void); //AD中断服务程序
void Serial_Port_Initial(void); //串口初始化原型
void Send_UART(uint8); //发送数据原型
void UART_Interrupt_Receive(void); //中断接收
void Timer0_Init(void); //定时器0初始化,定时1MS
void Timer0_Interrupt(void); //定时器中断服务程序
bit UTL_DelayTime(uint16 ); //延时程序
uint8 Read_Data(uint16); //从EEPROM中读数据
void Write_Data(uint8,uint16); //向EEPROM中写数据
void Erase_Data(uint16); //将EEPROM中的数据擦除
void IAP_Disable(void); //关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态
void Delays(void); //软件延时程序
void Display_LED(void); //测试灯闪烁
uint32 idata AD_Data; //AD结果变量
uint8 idata k=0; //AD采样次数计录
uint32 idata AD_Data1=0; //AD结果变量1
uint32 idata AD_Data2=0; //AD结果
uint32 idata __dwTemp; //此为时间计数变量
uint16 idata __wTemp; //此为时间计数变量
uint16 idata Data=0; //AD结果变量
uint32 data __dwCountSystem=0; //定时计数值
uint8 IAP_BYTE_READ =1; //字节读
uint8 IAP_BYTE_PROGRAM =2; //字节编程,可以将1 写成0,要将1 变成0,必须执行字节编程
uint8 IAP_SECTOR_ERASE =3; //扇区擦除,可以将0 擦成1,要将0 变成1,必须擦除整个扇区
uint8 ENABLE_IAP =0x80; //系统工作时钟<30MHz 时,对IAP_CONTR 寄存器设置此值
main()
{
AUXR |=0xC0; //d=1,定时方式的分频系数改变,采用1T模式
Delays(); //延时一小断时间有利于串口的初始化
Display_LED(); //程序开始执行一小段的闪烁程序
Serial_Port_Initial(); //串口初始化
Timer0_Init(); //定时器0初始化,定时1MS
Erase_Data(0x3200); //擦除扇区
Write_Data(0x00,0x3200); //写数据
Data=Read_Data(0x3200); //读取数据
IAP_Disable(); //关闭IAP功能
AD_Iint(); //AD初始化
while(1)
{
Send_UART((uint8)(AD_Data2>>8)); //发送AD数据,分两次发送
Send_UART((uint8)(AD_Data2));
Erase_Data(0x2600); //擦除扇区
Write_Data((uint8)(AD_Data2>>8),0x2600); //写数据
Erase_Data(0x2800); //擦除扇区
Write_Data((uint8)(AD_Data2),0x2800); //写数据
UTL_DelayTime(10);
}
}
void Display_LED(void)//LED灯闪烁
{
unsigned char i=0;
for(i=0;i<5;i++)
{
P4_0=1;
Delays();
P4_0=0;
Delays();
}
}
/******************************************************************************
函数:AD_Iint()
功能:AD初始化
说明:设置相应的AD参数,并且打开AD中断,可用中断方式,亦可用查询方式
******************************************************************************/
void AD_Iint(void)
{
P1ASF = 0xFF; //设置P1的所有I/0口都为AD输入口
//A/D转换控制寄存器 ADC_POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0
ADC_CONTR = 0xE7; // 1 1 1 0 0 1 1 1
UTL_DelayTime(1); //ADC_POWER =1.开ADC 电源, 第一次使用时要打开内部模拟电源
// 可适当加延时,1mS 以内就足够了
AUXR1= 0x04; // ADRJ=AUXR^4 设为1, 10 位A/D 转换结果的高2 位存放在ADC_RES 中低2位,
// 低8位存放在ADC_RESL 中
ADC_CONTR = 0xEF; //开始AD转换
EADC = 1; // 允许ADC中断
EA = 1; // 打开总中断
}
/******************************************************************************
函数:AD_Interrupt()
功能:AD中断,对AD结果进行分析
说明:AD中断,可用中断方式,亦可用查询方式 ,此采用中断方式
******************************************************************************/
void AD_Interrupt(void) interrupt 5
{
k++;
ADC_CONTR = 0xE7; //AD关闭
EADC = 0; //禁止AD中断
//UTL_DelayTime(1);
Data = ADC_RES*256+ADC_RESL; //AD采样出来的数值
AD_Data = Data; //存入数据
AD_Data1 = AD_Data1+AD_Data; //相加采样值
//AD_Data = (AD_Data*5000)>>10;
if(k==64) //采样64次之后进行平均求值
{
k=0;
AD_Data2 = (AD_Data1*4893)>>16; //根据参考电压得到最终的数据
AD_Data1=0;
}
ADC_CONTR = 0xEF; //重新开始AD转换
EADC = 1;
}
/******************************************************************************
函数:Delays()
功能:软件延时
说明:本函数采用软件延时一定的时间
******************************************************************************/
void Delays(void)//延时
{
unsigned short j=0;
unsigned short g=0;
for(j=0;j<100;j++)
{
for(g=0;g<5000;g++)
{
;
}
}
}
/******************************************************************************
函数:Read_Data()
功能:从EEPROM中读数据
说明:设置相应的IAP参数,最后连续送5A和A5到IAP_TRIG中开启IAP.读取数据,返回
******************************************************************************/
uint8 Read_Data(uint16 Flash_Address) //从EEPROM中读数据
{
uint8 Dat=0;
IAP_CONTR =ENABLE_IAP ; //打开 IAP 功能, 设置 Flash 操作等待时间
IAP_CMD =IAP_BYTE_READ ;//设置为IAP/ISP/EEPROM 字节读模式命令
IAP_ADDRH =(uint8)(Flash_Address>>8); //设置目标单元地址的高8 位地址
IAP_ADDRL =(uint8)Flash_Address; //设置目标单元地址的低8 位地址
EA=0;
IAP_TRIG =0x5A ; //先送5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG =0xA5 ; //送完A5h 后,ISP/IAP 命令立即被触发起动
EA=1;
;
Dat=IAP_DATA ; //读出的数据在IAP_DATA 单元中,送入累加器A
return(Dat);
}
/******************************************************************************
函数:Write_Data()
功能:向EEPROM中写数据
说明:设置相应的IAP参数,最后连续送5A和A5到IAP_TRIG中开启IAP,自动进行写数据操作.
******************************************************************************/
void Write_Data(uint8 Fl,uint16 Flash_Address) //向EEPROM中写数据
{
IAP_CONTR =ENABLE_IAP ; //打开 IAP 功能, 设置 Flash 操作等待时间
IAP_CMD =IAP_BYTE_PROGRAM ;//设置为IAP/ISP/EEPROM 字节读模式命令
IAP_ADDRH =(uint8)(Flash_Address>>8); //设置目标单元地址的高8 位地址
IAP_ADDRL =(uint8)Flash_Address; //设置目标单元地址的低8 位地址
IAP_DATA =Fl;
EA=0;
IAP_TRIG =0x5A ; //先送5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG =0xA5 ; //送完A5h 后,ISP/IAP 命令立即被触发起动
EA=1;
;
}
/******************************************************************************
函数:Erase_Data()
功能:EEPROM扇区擦除
说明:设置相应的IAP参数,最后连续送5A和A5到IAP_TRIG中开启IAP.自动进行扇区擦除
******************************************************************************/
void Erase_Data(uint16 Flash_Address)
{
IAP_CONTR =ENABLE_IAP ; //打开 IAP 功能, 设置 Flash 操作等待时间
IAP_CMD =IAP_SECTOR_ERASE ; //设置为IAP/ISP/EEPROM 字节读模式命令
IAP_ADDRH =(uint8)(Flash_Address>>8); //设置目标单元地址的高8 位地址
IAP_ADDRL =(uint8)Flash_Address; //设置目标单元地址的低8 位地址
EA=0;
IAP_TRIG =0x5A ; //先送5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG =0xA5 ; //送完A5h 后,ISP/IAP 命令立即被触发起动
EA=1;
;
}
/******************************************************************************
函数:IAP_Disable()
功能:关闭 IAP 功能
说明:以下具体说时
******************************************************************************/
void IAP_Disable(void)
{
//关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
IAP_CONTR =0 ; //关闭 IAP 功能
IAP_CMD =0 ; //清命令寄存器,使命令寄存器无命令,此句可不用
IAP_TRIG =0 ; //清命令触发寄存器,使命令触发寄存器无触发,此句可不用
IAP_ADDRH =0xFF ; //送地址高字节单元为FF,指向非EEPROM 区
IAP_ADDRL =0xFF ; //送地址低字节单元为FF,防止误操作
}
/******************************************************************************
函数:Serial_Port_Initial()
功能:串口初始化
说明:串口采用串口1,方式1来传送接收数据,使用独立波特率发生器作为波特率发生器
采用4800bps传输速率。
******************************************************************************/
void Serial_Port_Initial(void)//串口初始化
{
SCON=0x50; //采用串口方式1。
BRT=RELOAD; //装入重装数
//AUXR 8Eh Auxiliary Register T0x12 T1x12 UART_M0x6 BRTR S2SMOD BRTx12 EXTRAM S1BRS
AUXR|=0x11; //00010001;开启BRTR即启动Serial,开启S1BRS即使用独立波特率发生器作
//为波特率发生器
ES=1; //允许串口中断
EA=1; //开启总中断
}
/******************************************************************************
函数:Send_UART()
功能:串口发送数据
说明:串口采用串口1,方式1来传送接收数据,使用独立波特率发生器作为波特率发生器
采用4800bps传输速率。
******************************************************************************/
void Send_UART(uint8 i)//发送数据
{
ES=0;
TI=0;
SBUF=i;
while(TI==0);
TI=0;
ES=1;
}
/******************************************************************************
函数:UART_Interrupt_Receive()
功能:串口接收数据
说明:串口采用串口1,方式1来传送接收数据,使用独立波特率发生器作为波特率发生器
采用4800bps传输速率。
******************************************************************************/
void UART_Interrupt_Receive(void) interrupt 4//中断接收
{
uint8 k=0;
if(RI==1)
{
RI=0;
k=SBUF;
Send_UART(k+1);
}
else TI=0;
}
/******************************************************************************
函数:Timer0_Iint()
功能:定时器0初始化,定时1MS
说明:请根据具体情况调整定时值
******************************************************************************/
void Timer0_Init(void)
{
TMOD |= 0x01; /* TMOD: timer 0, mode 1, 16-bit 0001 */
TH0 = (65536-24000)/256;
TL0 = (65536-24000)%256; //1ms
TR0 = 1; /* TR1: timer 0 run */
ET0=1;
EA=1;
}
/********************************************************************
// Function : UTL_DelayTime
// Description : Delay until time out
// Arguments : wCount : the delay time
// btBreak : FALSE, wait until time out
// : TRUE, leave immediately
// Return : TRUE
// Side Effect :
// *********************************************************************/
bit UTL_DelayTime(uint16 wCount)
{
__wTemp= wCount;
__dwTemp= __dwCountSystem;
while ( ( __dwCountSystem- __dwTemp ) < __wTemp )
{
}
return 1;
}
/* *********************************************************************
// Function : ISR_Timer0; ET1(SFR, bit 3 of IE)
// : Timer1, mode 1, 16 bits counter
// Description : 1. receive the internal timer counting(When up counter overflow)
// : 2. must re-load the TH1, TL1 value
// 3. The Timer will scan Key, monitor system and Error-Concealment
// Arguments :
// Return : none
// Side Effect :
// *********************************************************************/
void ISR_Timer0(void) interrupt 1 using 1
{
//BYTE bKey;
__dwCountSystem++;
TH0 = (65536-24000)/256; // reload counter
TL0 = (65536-24000)%256; //1ms
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -