STC12C5A60S2单片机的10位AD转换程序
- 格式:doc
- 大小:14.00 KB
- 文档页数:2
P2口接数码管,4个数码管选通端由P1.4~P1.7控制,分别控制千位~个位。
STC单片机P1口自带AD转换。
ADC_CONTR EQU 0C5H ;A/D转换寄存器ADC_RES EQU 0C6H ;8位A/D转换结果寄存器ADC_RES2 EQU 0BEHP1ASF EQU 9DH ;P1口中的相应位作为模拟功能使用时的控制寄存器,如做A/D用,相应位要置1ADC_Power_On_Speed_Channel_2 EQU 11100010BP1M0 EQU 91HP1M1 EQU 92HADC_Channel_2_Result EQU 32H ;2通道A/D转换结果ADC_Channel_2_Result2 EQU 33HORG 0000HMOV SP, #6FHAD1:;设置堆栈ACALL ADC_Power_On ;开ADC电源, 第一次使用时要打开内部模拟电源ACALL Set_P12_ASF ;开ADC电源, 可适当加延时,1mS 以内就足够ACALL Set_P12_ASF ;设置P1.2 为模拟功能口ACALL Set_ADC_Channel_2 ;设置P1.2 作为A/D转换通道ACALL Get_AD_Result ; AD转换结果LCALL ZHUANHUA1LCALL DISPSJMP AD1;A/D转换电源,晶振为22.1184MHz,时间为1.280758msADC_Power_On:PUSH ACCORL ADC_CONTR, #80H ;开A/D转换电源MOV A, #20HACALL DELAY ;开A/D转换电源后要加延时,1mS以内就足够了POP ACCRET;设置P1.2为模拟功能,晶振为22.1184MHz,时间为0.000496msSet_P12_ASF:PUSH ACCMOV A, #00000100BORL P1ASF, AORL P1M0, AORL P1M1, APOP ACCRET;选择P1.2作为A/D转换通道,晶振为22.1184MHz,时间为0.000363msSet_ADC_Channel_2:MOV ADC_CONTR, #ADC_Power_On_Speed_Channel_2;选择P1.2作为A/D转换通道;更换A/D 转换通道后要适当延时, 使输入电压稳定;以后如果不更换A/D 转换通道的话, 不需要加延时RET;将AD转换结果存入寄存器中,晶振为22.1184MHz,时间为0.050516msGet_AD_Result:PUSH ACC ;入栈保护MOV ADC_RES, #0ORL ADC_CONTR, #00001000B ;启动AD 转换NOP ;在对ADC_CONTR寄存器进行写操作后,要加4个空操作延时,才能够正确读到ADC_CONTR的值NOPNOPNOPWait_AD_Finishe:MOV A, #00010000B ;判断AD 转换是否完成ANL A, ADC_CONTRJZ Wait_AD_Finishe ;AD 转换尚未完成, 继续等待ANL ADC_CONTR, #11100111B ;清0 ADC_FLAG, ADC_START 位, 停止A/D转换MOV A, ADC_RESMOV ADC_Channel_2_Result,A ;将转换高8位结果存入ADC_Channel_2_Result中MOV A,ADC_RES2MOV ADC_Channel_2_Result2,A ;将转换低2位结果存入ADC_Channel_2_Result1中MOV A,ADC_Channel_2_Result ;将转换结果的高两位存入ADC_Channel_2_Result中,低8位存入ADC_Channel_2_Result1中RL ARL AANL A,#03HMOV 61H,A ;将转换结果的高两位存入61H中MOV A,ADC_Channel_2_ResultRL ARL AANL A,#0FCHMOV 42H,AMOV A,ADC_Channel_2_Result2ANL A,#03HORL A,42HMOV 60H,A ;将转换低8位结果存入60H中POP ACCRET;转换值源码,晶振为22.1184MHz,时间为0.013055msZHUANHUA1:PUSH ACCMOV R2,#00H ;十六进制转换十进制MOV R3,#00HMOV R4,#16YI1: MOV A,60HRLC AMOV 60H,AMOV A,61HRLC AMOV 61H,AMOV A,R2ADDC A,R2DA AMOV R2,AMOV A,R3ADDC A,R3DA AMOV R3,ADJNZ R4,YI1MOV A,R3MOV B,#16 ;取出千位百位DIV ABMOV 50H,AMOV 51H,BMOV A,R2MOV B,#16 ;取出十位个位DIV ABMOV 52H,AMOV 53H,BMOV R0,#50HPOP ACCRETDISP:MOV DPTR,#TAB;显示千位CLR P1.4MOV R0,#50HMOV A,@R0MOVC A,@A+DPTRMOV P2,AACALL DELAYSETB P1.4CLR P1.5 ;显示百位INC R0MOV A,@R0MOVC A,@A+DPTRMOV P2,AACALL DELAYSETB P1.5SETB P1.3CLR P1.6 ;显示十位INC R0MOV A,@R0MOVC A,@A+DPTRMOV P2,AACALL DELAYSETB P1.6CLR P1.7 ;显示个位INC R0MOV A,@R0MOVC A,@A+DPTRMOV P2,AACALL DELAYSETB P1.7RET;开启转换电源延时时间,晶振为22.1184MHz,时间为0.090833msDELAY:MOV R2,#02HDL5:MOV R3 ,#8FHDL2:MOV R4 ,#18HDL1:NOPNOPDJNZ R4,DL1DJNZ R3,DL2DJNZ R2,DL5RETTAB:DB 44H , 0DEH , 62H , 52H , 0D8H , 51H , 41H , 0D6H , 40H ,50H,04H,9EH,22H,12H,98H,11H,01H,96H,00H,10H ;前10位不带小数点后19为带小数点字码表END。
A/D转换测试程序(ADC查询方式)#include “stc12c5a.h”//头文件在STC公司主页上下载#include ”intrins。
h"//与STC12C5A60S2单片机ADC相关的寄存器说明//Sfr ADC_CONTR = 0xBC;//AD转换控制寄存器Sfr ADC_RES = 0xBD;//AD转换结果寄存器高Sfr ADC_RESL = 0xBE;//AD转换结果寄存器低Sfr P1ASF = 0x9D;//P1口模拟转换功能控制寄存器Sfr AURX1 = 0xA2;//AD转换结果存储方式控制位#define ADC_POWER 0x80 //ADC电源开#define ADC_FLAG 0x10 //ADC结束标志位#define ADC_START 0x08 //ADC启动控制位设为开#define ADC_SPEEDLL 0x00 //设为540个时钟周期ADC一次#define ADC_SPEEDL 0x20 //设为360个时钟周期ADC一次#define ADC_SPEEDH 0x40 //设为180个时钟周期ADC一次#define ADC_SPEEDHH 0x60 //设为90个时钟周期ADC一次void AD_init(void);void delay(unsigned int a);unsigned int AD_get(unsigned char n);float AD_work(unsigned char n);void main(){unsigned char i;AD_init();while(1){for(i=0;i<8;i++){AD_work(i);delay(20);}}}unsigned int AD_get(unsigned char n) //第n通道ADC采样函数{unsigned int adc_data;ADC_RES = 0; //清零ADC_CONTR=ADC_POWER|ADC_SPEEDLL|n|ADC_START;//打开AD转换电源、设定转换速度、设定通道号、AD转换开始_nop_();_nop_();_nop_();_nop_();//要经过4个CPU时钟的延时,其值才能够保证被设置进ADC_CONTR 寄存器while(!(ADC_CONTR&ADC_FLAG)); //等待转换完成adc_data=ADC_RES; //转换结果计算,取8位结果ADC_CONTR&=~ADC_FLAG;//关闭AD转换,ADC_FLAG位由软件清0return adc_data; //返回ADC的值}float AD_work(unsigned char n){float AD_val;//定义处理后的数值AD_val为浮点数unsigned char i;for(i=0;i<100;i++)AD_val+=AD_get(n);//转换100次求平均值(提高精度)AD_val/=100;AD_val=(AD_val*5)/256;//AD的参考电压是单片机上的5v,所以乘5即为实际电压值return AD_val;}void AD_init(void){P1ASF = 0xff;//P1口全部作为模拟功能A/D使用ADC_RES = 0; //清零转换结果寄存器高8位ADC_CONTR = ADC_POWER|ADC_SPEEDLL;delay(2);//等待1ms,让AD电源稳定}void delay(unsigned int a){unsigned int i;while (a-—){i=5000;while(i--);}}。
A/D转换测试程序(ADC查询方式)#include “stc12c5a.h”//头文件在STC公司主页上下载#include ”intrins.h”//与STC12C5A60S2单片机ADC相关的寄存器说明//Sfr ADC_CONTR = 0xBC;//AD转换控制寄存器Sfr ADC_RES = 0xBD;//AD转换结果寄存器高Sfr ADC_RESL = 0xBE;//AD转换结果寄存器低Sfr P1ASF = 0x9D;//P1口模拟转换功能控制寄存器Sfr AURX1 = 0xA2;//AD转换结果存储方式控制位#define ADC_POWER 0x80 //ADC电源开#define ADC_FLAG 0x10 //ADC结束标志位#define ADC_START 0x08 //ADC启动控制位设为开#define ADC_SPEEDLL 0x00 //设为540个时钟周期ADC一次#define ADC_SPEEDL 0x20 //设为360个时钟周期ADC一次#define ADC_SPEEDH 0x40 //设为180个时钟周期ADC一次#define ADC_SPEEDHH 0x60 //设为90个时钟周期ADC一次void AD_init(void);void delay(unsigned int a);unsigned int AD_get(unsigned char n);float AD_work(unsigned char n);void main(){unsigned char i;AD_init();while(1){for(i=0;i〈8;i++){AD_work(i);delay(20);}}}unsigned int AD_get(unsigned char n) //第n通道ADC采样函数{unsigned int adc_data;ADC_RES = 0;//清零ADC_CONTR=ADC_POWER|ADC_SPEEDLL|n|ADC_START;//打开AD转换电源、设定转换速度、设定通道号、AD转换开始_nop_();_nop_();_nop_();_nop_();//要经过4个CPU时钟的延时,其值才能够保证被设置进ADC_CONTR 寄存器while(!(ADC_CONTR&ADC_FLAG));//等待转换完成adc_data=ADC_RES;//转换结果计算,取8位结果ADC_CONTR&=~ADC_FLAG;//关闭AD转换,ADC_FLAG位由软件清0return adc_data; //返回ADC的值}float AD_work(unsigned char n){float AD_val; //定义处理后的数值AD_val为浮点数unsigned char i;for(i=0;i〈100;i++)AD_val+=AD_get(n); //转换100次求平均值(提高精度)AD_val/=100;AD_val=(AD_val*5)/256; //AD的参考电压是单片机上的5v,所以乘5即为实际电压值return AD_val;}void AD_init(void){P1ASF = 0xff; //P1口全部作为模拟功能A/D使用ADC_RES = 0;//清零转换结果寄存器高8位ADC_CONTR = ADC_POWER|ADC_SPEEDLL;delay(2);//等待1ms,让AD电源稳定}void delay(unsigned int a){unsigned int i;while (a——){i=5000;while(i--);}}。
//--------------------------------------------------------------------------------//新一代1T 8051系列单片机内核特殊功能寄存器C51 Core SFRs// 7 6 5 4 3 2 1 0 Reset Valuesfr ACC = 0xE0; //Accumulator 0000,0000sfr B = 0xF0; //B Register 0000,0000sfr PSW = 0xD0; //Program Status Word CY AC F0 RS1 RS0 OV F1 P 0000,0000//-----------------------------------sbit CY = PSW^7;sbit AC = PSW^6;sbit F0 = PSW^5;sbit RS1 = PSW^4;sbit RS0 = PSW^3;sbit OV = PSW^2;sbit P = PSW^0;//-----------------------------------sfr SP = 0x81; //Stack Pointer 0000,0111sfr DPL = 0x82; //Data Pointer Low Byte 0000,0000sfr DPH = 0x83; //Data Pointer High Byte 0000,0000//--------------------------------------------------------------------------------//新一代1T 8051系列单片机系统管理特殊功能寄存器// 7 6 5 4 3 2 1 0 Reset Valuesfr PCON = 0x87; //Power Control SMOD SMOD0 LVDF POF GF1 GF0 PD IDL 0001,0000// 辅助寄存器7 6 5 4 3 2 1 0 Reset Valuesfr AUXR = 0x8E; //Auxiliary Register T0x12 T1x12 UART_M0x6 BRTR S2SMOD BRTx12 EXTRAM S1BRS 0000,0000//-----------------------------------sfr AUXR1 = 0xA2; //Auxiliary Register 1 - PCA_P4 SPI_P4 S2_P4 GF2 ADRJ - DPS 0000,0000/*PCA_P4:0, 缺省PCA 在P1 口1,PCA/PWM 从P1 口切换到P4 口: ECI 从P1.2 切换到P4.1 口,PCA0/PWM0 从P1.3 切换到P4.2 口PCA1/PWM1 从P1.4 切换到P4.3 口SPI_P4:0, 缺省SPI 在P1 口1,SPI 从P1 口切换到P4 口: SPICLK 从P1.7 切换到P4.3 口MISO 从P1.6 切换到P4.2 口MOSI 从P1.5 切换到P4.1 口SS 从P1.4 切换到P4.0 口S2_P4:0, 缺省UART2 在P1 口1,UART2 从P1 口切换到P4 口: TxD2 从P1.3 切换到P4.3 口RxD2 从P1.2 切换到P4.2 口GF2: 通用标志位ADRJ:0, 10 位A/D 转换结果的高8 位放在ADC_RES 寄存器, 低2 位放在ADC_RESL 寄存器1,10 位A/D 转换结果的最高2 位放在ADC_RES 寄存器的低2 位, 低8 位放在ADC_RESL 寄存器DPS: 0, 使用缺省数据指针DPTR01,使用另一个数据指针DPTR1*///-----------------------------------sfr WAKE_CLKO = 0x8F; //附加的SFR WAK1_CLKO/*7 6 5 4 3 2 1 0 Reset ValuePCAWAKEUP RXD_PIN_IE T1_PIN_IE T0_PIN_IE LVD_WAKE _ T1CLKO T0CLKO 0000,0000Bb7 - PCAWAKEUP : PCA 中断可唤醒powerdown。
用于STC单片机内置10位AD转换的代码+【软件滤波】
上面这段GetADCResult()是原来的AD采集,没什么变化,看看就行了GetResult()这个是软件滤波的,10位AD的之前弄滤波总出错,今天刚弄好。
关键在于(unsigned long)(),不加这个就总出错!计算过程中溢出,感觉好像是计
算时自动降位了
ulong GetADCResult(uchar ch){ulong AD_result;ADC_CONTR = ADC_POWER
| ADC_SPEEDLL | ch | ADC_START;_nop_(); //Must
wait before inquiry_nop_();_nop_();_nop_();while (!(ADC_CONTR &
ADC_FLAG));//Wait complete flagADC_CONTR &= ~ADC_FLAG; //Close ADCAD_result=ADC_RES*4+ADC_RESL; return AD_result; //Return ADC result 10bit}ulong GetResult(uchar ch) //滤波段{ulong
AD_result=0,AD_result1=0;ulong AD_max,AD_min,AD_temp;char
AD_i,AD_o;for(AD_i=0;AD_i方法是基于:去除最大最小值后平均。
共采样了
33次去掉9个后的结果平均值,我自己做电压表,速度足够!如果嫌慢的话可
以把AD_itips:感谢大家的阅读,本文由我司收集整编。
仅供参阅!。
STC12C5A60S2单片机的10位AD转换程序
#include"stc12c5a.h" //头文件在STC公司主页上下载
#include"stdio.h" //输入输出函数
#include"intrins.h"
//------------------------------------------------------------------------------
void AD_init(); //初始化AD
void serial_init();
void delay(unsigned int a);
float AD_work(unsigned char channel);
unsigned int AD_get(unsigned char channel);
//------------------------------------------------------------------------------
void main() //主程序
{
AD_init();??? //A/D转换初始化
serial_init();?? //串口初始化
while(1)
{
?? unsigned char i;
?? for(i=0;i<8;i++) //循环发送P1.0-P1.7的转换数值
?? {
??? TI=1;??? //使用printf函数前须先将发送标志位TI置1
??? printf("The P1.%bd voltage is %f\n",i,AD_work(i));
??? TI=0;
??? delay(1000); //延时约1s
?? }
}
}
//------------------------------------------------------------------------------
unsigned int AD_get(unsigned char channel)
{
ADC_CONTR=0x88|channel;??? //开启AD转换1000 1000 即POWER SPEED1 SPEED0 ADC_FLAG?? ADC_START CHS2 CHS1 CHS0
_nop_(); _nop_(); _nop_(); _nop_(); //要经过4个CPU时钟的延时,其值才能够保证被设置进ADC_CONTR 寄存器
while(!(ADC_CONTR&0x10));??? //等待转换完成
ADC_CONTR&=0xe7;????? //关闭AD转换,ADC_FLAG位由软件清0
return(ADC_RES*4+ADC_RESL);?? //返回AD转换完成的10位数据(16进制)
}
//------------------------------------------------------------------------------
float AD_work(unsigned char channel)
{
float AD_val;???? //定义处理后的数值AD_val为浮点数
unsigned char i;
for(i=0;i<100;i++)
AD_val+=AD_get(channel); //转换100次求平均值(提高精度)
AD_val/=100;
AD_val=(AD_val*5)/1024; //AD的参考电压是单片机上的5v,所以乘5即为实际电压值return AD_val;
}
//------------------------------------------------------------------------------
void delay(unsigned int a) //延时约1ms
{
unsigned int i;
while (--a!=0)
for(i=600;i>0;i--);?? //1T单片机i=600,若是12T单片机i=125
}
//------------------------------------------------------------------------------
void serial_init()
{
TMOD=0x20;
TH1=0xfd;
TL1=0xfd; //设置9600波特率
SCON=0x50; //串口方式1,允许接收
TR1=1;
}
//------------------------------------------------------------------------------
void AD_init()
{
P1ASF=0xff; //P1口全部作为模拟功能AD使用
ADC_RES=0;?? //清零转换结果寄存器高8位
ADC_RESL=0; //清零转换结果寄存器低2位
ADC_CONTR=0x80;//开启AD电源
delay(2);?? //等待1ms,让AD电源稳定
}
/*。