STC12C5A60S2AD功能的使用
- 格式:doc
- 大小:94.00 KB
- 文档页数:5
STC12C5A60S2中的AD转换逐次逼近原理AD 里面包含da,当输入电压Vin时,da的最高位是1,即为0.5Vref与输入信号比较,如果输入大于0.5Vref则比较器输出为1,同时da的最高位为1,反之DA最高位则为0,通过8次比较后得到8个01数据即完成ad转换。
现在说下程序中用到stc12单片机两个寄存器ADC_CONTR;主要用来配置ad启动的工作模式;还有个result的寄存器程序中的注意点:配置完ADC_CONTR后要延时4个时钟周期先把程序附上#include "stc12.h"#include "intrins.h"#include "ad.h"uint ad;#define ADC_POWER 0X80 //ADC最高位给adc部分供电,类似于片选#define ADC_START 0X08 //模数转换启动控制位#define ADC_FLAG 0x10 //ad转换需要时间,这个是转换完成标志位#define ADC_SPEEDLL 0X00 //540 clock#define ADC_SPEEDL 0X20 //360 clock#define ADC_SPEEDH 0X40 //180 clock#define ADC_SPEEDHH 0X60 //90 clockuchar ADCresult(uchar aa) //这里的参数是哪个口来ad转换{P1ASF=0X01; //这里的选择和用哪一个P1口作为ad采样ADC_CONTR=ADC_POWER|ADC_SPEEDLL|ADC_START|aa;//ADC_CONTR=0X88|aa;_nop_();_nop_();_nop_();_nop_();//设置ADC_CONTR寄存器后需加4个CPU时钟周期的延时,才能保证值被写入ADC_CONTR寄存器while (!(ADC_CONTR & ADC_FLAG)); //等待ADC_CONTR,这里的ADC_FLAG相当于一个常数,不是寄存器里面的某个位//while(!ADC_FLAG);//ADC_FLAG=0;ADC_CONTR &= ~ADC_FLAG; //Close ADC 将标志位清零等待下次硬件置1ad=(ADC_RES<<2)+ADC_RESL; //打开10位AD采集功能如果用8位AD 屏掉这句把下一句改为Vo=(float)(ADC_RESL)*500/256; 即可//ADC_RES结果寄存器的高2位;ADC_RES结果寄存器的低8位ad=(float)(ad)*5*100/1024; //Return ADCresult(为显示整数,这里将电压值扩大了十倍)//10位AD采集即2的10次方满值为1024 这里用1024表示5伏的电压//那么用采集到的数量值除以1024 在乘以5 得到的值就是采集的电压数值//这里又*100 是为了扩大100倍显示小数位//ADC_RES*(5/256)为采集的电压值然后扩大10倍便于计算return ad;}这里只是个ad.c源文件,这里有几个问题想说一下1.怎么知道是10位还是8位的ad结果;你可以在ADCresult(uchar aa)最前面加一条AUXR1&=0x04;什么意思呢,转换结果的低2位放在ADC_RES,高8位ADC_RESL 中2为什么不用//while(!ADC_FLAG);//ADC_FLAG=0;这两条因为ADC_FLAG相当于常量前面用宏定义而头文件里只有ADC_CONTR的地址映射;但是如果在头文件中用sbit ADC_FLAG=ADC_CONTR^4会出现错误,具体原因还不清楚先说到这吧。
#include”stc12c5a.h" //头文件在STC公司主页上下载#include"stdio.h"#include”intrins。
h”#define uchar unsigned char//—-—————---—————-----———————-—-——-————---—-—————————--————-————--—-—---—-—-—---void AD_init();//AD初始化函数void delay(unsigned int a); //延时函数float AD_work(unsigned char channel); //AD数值处理函数unsigned int AD_get(unsigned char channel);//AD转换函数unsigned char sh1,ge1,n1,m1,aa;int num,pwm,V,temp1;sbit PWM=P0^0; //定义PWM输出口为P0^0sbit key1=P0^1;sbit key2=P0^2;//--—---—----—----——---—-—-—————---—----——--———---———-———-———-—-—--————--—-——-—-void send(uchar data1){ES=0; //关闭中断TI=0;SBUF=data1;while(!TI); //等待发送完成TI=0;//中断标志位清0ES=1;//打开中断}void display() //串口发送AD{temp1=V;sh1=temp1/1000;ge1=(temp1%1000)/100;n1=((temp1%1000)%100)/10;send(sh1+48);send(’.');send(ge1+48);send(n1+48);send(’V');send(' ');}//--——-——-----—--—--———------———--————-—-——-—-——----———-—-—--—-—-———--—-—-——---—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位由软件清0return(ADC_RES*4+ADC_RESL); //返回AD转换完成的10位数据(16进制)}//-——-——----——-———————--—-----———-—-—-—-—-—-----————-——-——--—-——--—--—--—--—----float AD_work(unsigned char channel){double AD_val,AD_vale; //定义处理后的数值AD_val为浮点数unsigned char i;for(i=0;i<100;i++)AD_val+=AD_get(channel); //转换100次求平均值(提高精度)AD_val/=100;AD_vale=(AD_val*5000)/1024; //AD的参考电压是单片机上的5v,所以乘5即为实际电压值V=AD_vale;return V;}//--—-—----——--—------—--—-—---—----—----———-—--—---—————-———---—--—————---—————void delay(unsigned int a)//延时约1ms{unsigned int i;while (-—a!=0)for(i=600;i>0;i-—);}//-—--——-—----——--——--————-——-—-—-—--—--——-————---—-—----—-—--——-—----———-—-——-—//------—-———-——-—--—--——---————-————-—-——-—--—————-—-—--——-—————-—--———--——----void AD_init(){P1ASF=0xff;//P1口全部作为模拟功能AD使用ADC_RES=0;//清零转换结果寄存器高8位ADC_RESL=0;//清零转换结果寄存器低2位ADC_CONTR=0x80;//开启AD电源delay(2);//等待1ms,让AD电源稳定}void anjian(){if(pwm!=100) //加到100不继续加{if(key1==0){delay(10);if(key1==0){pwm++;aa=1;while(!key1);}}}if(pwm!=0) //减到0不继续减{if(key2==0){delay(10);if(key2==0){aa=1;pwm-—;while(!key2);}}}}void main(){AD_init(); //AD初始化TMOD=0x21;TH1=0xfd;TL1=0xfd; //设置9600波特率SCON=0x50; //串口方式1,允许接收TH0=(65536—7)/256; //装初值,设定PWM频率TL0=(65536—7)%256;ET0=1;TR0=1;TR1=1;SM0=0;SM1=1;REN=1;ES=1;EA=1;pwm=50;//占空比为50%while(1){unsigned char i;i=0;//发送P1^i的转换数值(P10口)AD_work(i); //读取AD电压display();if(V〉=3000){aa=0;pwm=0;//占空比为0}if(V〈3000){if(aa==0)pwm=50;anjian();}}}void T0_time()interrupt 1 //中断时间为0.01ms,因PWM输出口输出高低电平共100次为1个周期,所以PWM的周期为1ms,频率为1KHZ{TH0=(65536—7)/256;TL0=(65536-7)%256;num++;if(num〈=pwm)PWM=1;elsePWM=0;if(num==100)num=0;}。
STC12C5A60S2的ADC+PWM功能STC12C5A60S2单片机的A/D转换口在P1口(P1.7-P1.0),有8路10位高速A/D转换器,速度可达到250 KHz(25万次/秒)。
脉宽调制(PWM)是一种使用程序来控制波形占空比、周期、相位波形的技术。
STC12C5A60S2单片机的PAC模块可以通过程序设定,使其工作于8位PWM模式。
下面是一段将ADC和PWM结合起来应用的程序:/************************************************ ***************时间:2012.12.1晶振:12MHz功能描述:AD采集电位器的电压信号,然后信号以PWM 信号输出控制LED的亮度(调节电位器)当电位器两端的电压大时,LED较亮,同时用1602显示采集的电压值AD采集通道:P1.0PWM输出: P1.3************************************************* **************/#include;#include;unsigned int result,ge,shifen,baifen;unsigned charseg[10]={'0','1','2','3','4','5','6','7','8','9'} ;//要显示字符sbit RS = P2^4; //命令数据sbit RW = P2^5; //写还是读sbit EN = P2^6; //使能端#define RS_CLR RS=0#define RS_SET RS=1#define RW_CLR RW=0#define RW_SET RW=1#define EN_CLR EN=0#define EN_SET EN=1#define DataPort P0/*------------------------------------------------uS延时函数,含有输入参数 unsigned char t,无返回值unsigned char 是定义无符号字符变量,其值的范围是 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时长度如下 T=tx2+5 uS------------------------------------------------* /void DelayUs2x(unsigned char t){while(--t);}/*------------------------------------------------mS延时函数,含有输入参数 unsigned char t,无返回值unsigned char 是定义无符号字符变量,其值的范围是 0~255 这里使用晶振12M,精确延时请使用汇编------------------------------------------------* /void DelayMs(unsigned char t){while(t--){//大致延时1mSDelayUs2x(245);DelayUs2x(245);}}/*------------------------------------------------判忙函数------------------------------------------------* /bit LCD_Check_Busy(void){DataPort= 0xFF;RS_CLR;RW_SET;EN_CLR;_nop_();EN_SET;return (bit)(DataPort & 0x80);}/*------------------------------------------------写入命令函数------------------------------------------------*/void LCD_Write_Com(unsigned char com){while(LCD_Check_Busy()); //忙则等待RS_CLR;RW_CLR;EN_SET;DataPort= com;_nop_();EN_CLR;}/*------------------------------------------------写入数据函数------------------------------------------------* /void LCD_Write_Data(unsigned char Data){while(LCD_Check_Busy()); //忙则等待RS_SET;RW_CLR;EN_SET;DataPort= Data;_nop_();EN_CLR;}/*------------------------------------------------清屏函数------------------------------------------------* /void LCD_Clear(void){LCD_Write_Com(0x01);DelayMs(5);}/*------------------------------------------------写入字符串函数------------------------------------------------* /void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s){{LCD_Write_Com(0x80 + x); //表示第一行}else{LCD_Write_Com(0xC0 + x); //表示第二行}while (*s){LCD_Write_Data( *s);s ++;}}/*------------------------------------------------写入字符函数------------------------------------------------* /void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data){{LCD_Write_Com(0x80 + x);}else{LCD_Write_Com(0xC0 + x);}LCD_Write_Data( Data);}/*------------------------------------------------LCD初始化函数------------------------------------------------* /void LCD_Init(void){LCD_Write_Com(0x38); /*显示模式设置*/DelayMs(5);LCD_Write_Com(0x38);DelayMs(5);LCD_Write_Com(0x38);DelayMs(5);LCD_Write_Com(0x38);LCD_Write_Com(0x08); /*显示关闭*/LCD_Write_Com(0x01); /*显示清屏*/LCD_Write_Com(0x06); /*显示光标移动设置*/ DelayMs(5);LCD_Write_Com(0x0C); /*显示开及光标设置*/ }/*------------------------------------------------ADC初始化函数------------------------------------------------* /void InitADC(){P1ASF =0x01;//使能P1口ADC功能ADC_RES = 0;ADC_CONTR = 0xc8;}/*------------------------------------------------主函数------------------------------------------------* /void main(void){LCD_Init();LCD_Clear();//清屏LCD_Write_String(5,0,"526lab");//(列,行,数据)LCD_Write_String(2,1,"Result:"); InitADC();IE=0xa0;//开中断while (1){//PWM初始化CCON=0;CMOD=0;//1MCCAP0H=CCAP0L=ADC_RES;CCAPM0=0x42;//开启PWMCR=1;//计时开始//调用显示LCD_Write_Char(9,1,seg[ge]);LCD_Write_Char(10,1,'.');LCD_Write_Char(11,1,seg[shifen]);LCD_Write_Char(12,1,seg[baifen]);LCD_Write_Char(13,1,'V');}}/*------------------------------------------------ADC中断处理函数------------------------------------------------* /void adc_isr() interrupt 5 using 1{unsigned int temp;temp=ADC_RES;result=temp*0.01953125*1000;ge=result/1000;shifen=result%1000/100;baifen=result%100/10;ADC_CONTR = 0xc8;//开启转换}12C5A60S2.h的头文件//--------------------------------------------------------------------------------//新一代 1T 8051系列单片机内核特殊功能寄存器 C51 Core SFRs// 7 6 5 4 3 2 1 0Reset 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 Byte0000,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 0Reset Valuesfr AUXR = 0x8E; //Auxiliary Register T0x12 T1x12 UART_M0x6 BRTR S2SMOD BRTx12 EXTRAM S1BRS0000,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。
STC12C5A60S2AD采集12864显示程序/************************************************************** *************** 文件名:AD_CAIYANG.C* 功能:使用AD采集电压显示在LCD* 说明:本程序是STC12C5A60S2单片机自带AD的采集数据并通过12864液晶串行模式显示的程序*************************************************************** *************/#include//#include#define uint unsigned int#define uchar unsigned charsbit CS=P2^4; //LCD12864串行通信片选sbit SID=P2^5; //LCD12864串行通信数据口sbit SCLK=P2^6; //LCD12864串行通信同步时钟信号sbit PSB=P2^3; //LCD12864并/串选择:H并行 L串行sbit jd1=P2^0; //继电器1控制引脚sbit jd2=P2^1; //继电器2控制引脚sbit fengming=P2^7; //蜂鸣器控制引脚sbit start=P1^0; //开始信号控制引脚unsigned int temp1,sh1,ge1,n1,m1;unsigned char ad_result_data[10]; //AD转换高八位unsigned char ad_result_low2[10]; //AD转换低八位unsigned char ad_result_total[10]; //AD转换总十位unsigned char ad_average_result; //AD转换十次的平均值unsigned char Ain,Vin;unsigned char b,t,R;char tp=0;unsigned char code ma1[6]={0xb5,0xe7,0xd1,0xb9,0xa1,0xc3}; //电压:unsigned char code ma2[]={"."};uchar code disp1[]={" LG "};uchar code disp2[]={" 电压采集 "};uchar code disp3[]={"超级电容检测工装"};unsigned char code num0[]={0xa3,0xb0};unsigned char code num1[]={0xa3,0xb1};unsigned char code num2[]={0xa3,0xb2};unsigned char code num3[]={0xa3,0xb3};unsigned char code num4[]={0xa3,0xb4};unsigned char code num5[]={0xa3,0xb5};unsigned char code num6[]={0xa3,0xb6};unsigned char code num7[]={0xa3,0xb7};unsigned char code num8[]={0xa3,0xb8};unsigned char code num9[]={0xa3,0xb9};//-------模块延时程序---------------------------- 1msvoid delay1ms(uint delay1ms) //STC11F60XE,22.1184M,延时1ms{uint i,j;for(;delay1ms>0;delay1ms--)for(i=0;i<7;i++)for(j=0;j<210;j++);}void delay(uint delay) //STC11F60XE,22.1184M,延时170us{uint i,j;for(;delay>0;delay--)for(i=0;i<124;i++);for(j=0;j<124;j++);}/*******************************************************AD转换程序*******************************************************/void AD_initiate() //初始化函数{ES=0;TMOD=0x21; //定时计数器方式控制寄存器,"自动重装,16位计数器".SCON=0x50; //串行控制寄存器,方便在串口助手那观察TH1=0xfa;TL1=0xfa;TR1=1;}void ADC_Power_On() //AD转换电{ADC_CONTR|=0x80; //打开AD转换电源delay(5); //必要的延时延时一会儿等待AD供电电源稳定}void get_ad_result() //取AD结果函数,它是十位AD转换,每十次平均,最后取低八位作为AD采样数据{uint i,q=0;for(i=0;i<10;i++){tp=0;ADC_RES=0; //高八位数据清零,STC12C5A60S2 AD数据寄存名与STC12C54××系列不同ADC_RESL=0; //低两位清零ADC_CONTR|=0x08; //启动AD转换while(!tp) //判断AD转换是否完成{tp=0x10;tp&=ADC_CONTR;}ADC_CONTR&=0xe7;ad_average_result=ADC_RES;q=q+ad_average_result;}ad_average_result=q/10;//ad_average_result=ad_average_result*4*5000/1024;}/************************AD转换结束***********************/void send_ad_result() //取AD结果函数发送到串口,方便调试{SBUF=n1;while(TI==0) ;TI=0;delay1ms(100);//SBUF=R>>4;}//---------------------电压采样程序-------------------------void caiyangP10() //测电压{P1M0|=0x01; //设P1_0为开漏模式如: P1_0= #00000000B P1M1|=0x01;ADC_CONTR=0xe0; //设置P1.0为输入AD转换口delay(2);get_ad_result(); //取转换数据Vin=ad_average_result;// R=Vin;}/*-----------写控制字到LCD12864------------*/void write_cmd(uchar cmd){uchar i;uchar i_data;i_data=0xf8; //命令控制字:11111000写指令11111010写数据11111100读状态 11111110读数据CS=1; //片选置高,才能进行读写操作SCLK=0;/*----------写命令控制字-----------------*/for(i=0;i<8;i++) //循环八次,每次读取一位数据{SID=(bit)(i_data&0x80); //bit表示取其最高位SCLK=0;SCLK=1; //正跳变写入指令i_data=i_data<<1; //左移一位}/*---------------------------------------*//*----------写指令高四位-----------------*/i_data=cmd;i_data=i_data&0xf0; //把低四位置0for(i=0;i<8;i++) //循环八次,每次读取一位数据{SID=(bit)(i_data&0x80); //bit表示取其最高位SCLK=0;SCLK=1; //正跳变写入指令i_data=i_data<<1; //左移一位}/*---------------------------------------*//*----------写指令低四位-----------------*/i_data=cmd;i_data=i_data<<4; //左移四位,把低四位的数据移到高四位,再把低四位置0for(i=0;i<8;i++) //循环八次,每次读取一位数据{SID=(bit)(i_data&0x80); //bit表示取其最高位SCLK=0;SCLK=1; //正跳变写入指令i_data=i_data<<1; //左移一位}/*-----------------------------------------*/CS=0; //把片选置低delay1ms(5); //延时是因为没有进行忙检测,适当的延时可以不进行忙检测}/*-----------------------------------------*//*------------写数据到LCD12864-------------*/void write_dat(uchar dat){uchar i;uchar i_data;i_data=0xfa;CS=1;for(i=0;i<8;i++){SID=(bit)(i_data&0x80);SCLK=0;SCLK=1;i_data=i_data<<1;}i_data=dat;i_data=i_data&0xf0;for(i=0;i<8;i++){SID=(bit)(i_data&0x80);SCLK=0;SCLK=1;i_data=i_data<<1;}i_data=dat;i_data=i_data<<4;for(i=0;i<8;i++){SID=(bit)(i_data&0x80);SCLK=0;SCLK=1;i_data=i_data<<1;}CS=0;delay1ms(5);}/*-----------------------------------------*//*--------------显示坐标-------------------*/void lcd_pos(uchar x,uchar y) //汉字显示坐标,x为哪一行,y 为哪一列{uchar pos;if(x==0)x=0x80; //第一行else if(x==1)x=0x90; //第二行else if(x==2)x=0x88; //第三行else if(x==3)x=0x98; //第四行pos=x+y; //显示哪一行(总共有4行)哪一竖(总共有8竖,每16列为1竖)write_cmd(pos);}/*-----------------------------------------*//*--------------显示8个汉字-------------------*/void disp_hanzi(uchar code *chn){uchar i;write_cmd(0x30); //基本指令操作方式for(i=0;i<16;i++) //16列*8个汉字=128(刚好)write_dat(chn[i]);}/*-----------------------------------------*//*--------------显示数字-------------------*/void disp_num(uchar code *chn){uchar i;write_cmd(0x30); //基本指令操作方式for(i=0;i<2;i++) //1个数字write_dat(chn[i]);}void disp_number(uchar num){switch(num){case 0: disp_num(num0);break;case 1: disp_num(num1);break;case 2: disp_num(num2);break;case 3: disp_num(num3);break;case 4: disp_num(num4);break;case 5: disp_num(num5);break;case 6: disp_num(num6);break;case 7: disp_num(num7);break;case 8: disp_num(num8);break;case 9: disp_num(num9);break;default: break;}}/*----------- --LCD初始化------------------*/ void lcd_init(){PSB=0;write_cmd(0x30); //基本指令write_cmd(0x02); //地址归位write_cmd(0x06); //游标右移write_cmd(0x0c); //整体显示write_cmd(0x01); //清屏}/*-----------------------------------------*/ void displayP10(){float ad1;//unsigned int temp1,sh1,ge1,n1,m1;//uchar code dis2[]={0x01,0x02,0x00};//ad1=x*7.8125; //电压修正uchar i;// ad1=Vin*3.9608; //具体线性参数由输入电压值调整,该值的测量范围为0-10.00V,5V左右的测量比较准确,//两端的最大误差为70mv,其他一般在40mv以内ad1=Vin*2;temp1=(int)ad1;/* sh1=temp1/1000; //十位ge1=(temp1%1000)/100; //个位n1=((temp1%1000)%100)/10; //小数点后一位m1=((temp1%1000)%100)%10; //小数点后二位 */sh1=temp1/1000; //十位ge1=(temp1%1000)/100; //个位n1=(temp1%100)/10; //小数点后一位m1=temp1%10; //小数点后二位//write_cmd(0x01);write_cmd(0x30); //基本指令操作方式lcd_pos(0,0);for(i=0;i<6;i++)write_dat(ma1[i]);lcd_pos(0,3);disp_number(sh1);lcd_pos(0,4);disp_number(ge1);lcd_pos(0,5);for(i=0;i<2;i++) write_dat(ma2[i]);lcd_pos(0,6);disp_number(n1);lcd_pos(0,7);disp_number(m1);lcd_pos(1,0);disp_hanzi(disp1); lcd_pos(2,0);disp_hanzi(disp2);lcd_pos(3,0);disp_hanzi(disp3); delay1ms(5);}init ()start=1;jd1=0;jd2=0;fengming=0;}void main(){EA=1;AD_initiate(); //初始化ADC_Power_On(); //开AD电源init();lcd_init();delay(10);while(1){caiyangP10(); //测电压if(start==0){delay(10)if(start==0){if(Vin*2>1)jd1=1;else if(Vin*2<1)jd2=1;}send_ad_result(); //Vin=Vin*4007; displayP10(); delay(10);}}。
S T C12C5A60S2系列单片机A D功能详解作者:裴博宇作者原本旨在对STC12C5A60S2(后文简称该单片机、12C单片机)系列单片机相对传统51内核单片机升级内容进行详细解析,和程序应用分析,但是由于时间原因只写到了AD的查询方式使用,抱歉了,如果有什么错误欢迎批评指正,但是申明本人是一个学生,文章也只适合于初学者,希望行业的老人不要骂的太狠。
本文以STC12C5A60S2系列单片机芯片手册为母本编写。
一、相关寄存器介绍12C单片机自带8路10位AD,要使用他就必须明确其相关寄存器:P1ASF 寄存器P1口模拟配置寄存器,地址:9DH,复位值:00H。
12C单片机的AD转换引脚与P1I/O口复用,P1ASF寄存器指定P1寄存器哪一位用于AD 转换,哪一位做I/O口用。
具体是,P1ASF寄存器的8位对应P1的8位,1代表做AD转换通道用,0代表做I/O口用。
不可位寻址。
ADC_CONTR寄存器ADC控制寄存器,地址BCH,复位值:00H。
位说明:ADC_CONTR.7(这种写法其实是有问题的,因为该寄存器不支持位寻址,仅供阅读方便)——ADC_POWER。
ADC开关,要使用AD转换功能该位必须置“1”。
开在初始化时直接将其置“1”,但考虑到能耗的因素,最好在使用时开启,使用结束后关闭。
ADC_CONTR.6——SPEED1、ADC_CONTR.5——SPEED2,AD转换速率控制寄存器。
00——540个时钟周期转换一次;01——360个时钟周期转换一次;10——180个时钟周期转换一次;11——90个时钟周期转换一次。
转换速率并非越快越好,当然从效率角度来讲我们希望他更快,但是转换速率愉快能耗越高,同时准确度越低,所以请选择一个合理的周期。
ADC_CONTR.5——FLAG,AD转换结束标志位。
当AD转换结束时,自动拉高,标志转换结束。
注意,需用软件拉低。
ADC_CONTR.4——SRART,AD转换启动位。
/*---------------------------------------------------------------------------------------------------------------------------*//*--************************功能【AD转换,PWM电压控制,液晶显示】**************************--*/ /*--************************芯片:【STC12C5A60S2】******************************--*//*--************************液晶:【LCD1602】***********************************--*//*--************************ADC管脚:【P1.7 】***************************--*//*--************************检测范围:【0.00~12.5V】***************************--*//*---------------------------------------------------------------------------------------------------------------------------*/#include "stc12c5a60s2.h"#include "intrins.h"#define uint unsigned int#define uchar unsigned char#define _Nop() _nop_()/*------------------------以下为LCD1602显示模块定义-----------------------*/unsigned char data_char_table[]= {"0123456789ABCDEF"}; //LCD数据unsigned char Lcd_Dis1_table[] = {"Setvalue: V"}; //第一行显示框架unsigned char pos_char_table[] = {" 9A.C0 "}; // 显示位置unsigned char Lcd_Dis2_table[] = {"V oltage : V"}; //第二行显示框架unsigned char num_char_table[] = {" 9A.CD V"}; // 显示位置float show;float NUM;static uchar ldata=50; //作为显示的数据sbit lcd_rs_port = P2^0; //定义LCD控制端口,根据硬件调整sbit lcd_rw_port = P2^1;sbit lcd_en_port = P2^2;#define lcd_data_port P0sbit key1 = P3^7; //定义按键1sbit key2 = P3^6; //定义按键2sbit key3 = P3^5; //定义按键3sbit key4 = P3^4; //定义按键4sbit key5 = P3^3; //定义按键5sbit key6 = P3^2; //定义按键6/************定义相应操作位***************/#define ADC_POWER 0x80 //ADC电源控制位,0:关闭,1:打开#define ADC_FLAG 0x10 //ADC结束标志位#define ADC_START 0x08 //ADC启动控制位#define ADC_SPEEDLL 0x00 //540 clocks___________选择转换速度/*------------------------以下为相关函数声明------------------------------*/void InitADC(); //ADC初始化uint GetADCResult(uchar ch);void Delay(uint n); //延时程序void delay_1ms(uchar x);void lcd_delay(uchar ms); //LCD1602 延时void lcd_busy_wait(); //LCD1602 忙等待void lcd_command_write(uint command); //LCD1602 命令字写入void lcd_system_reset(); //LCD1602 初始化void lcd_char_write(uint x_pos,y_pos,lcd_dat); //LCD1602 字符写入void lcd_bad_check(); //LCD1602 坏点检查void Num_to_Disp(uint i, uint Num); //显示数据处理void LcdDisp(uint j, uint num); //液晶显示函数void DelayMs(uchar ms);void init_PWM();void PWM1_change(uchar type,uchar change);void PWM1_set(uchar empty);/*-------------------------------- ADC 取值------------------------------*/uint GetADCResult(uchar ch){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 ADCreturn (ADC_RES*4 + ADC_RESL); //Return ADC result}/*---------------------------- 初始化ADC特殊功能寄存器-------------------*/void InitADC( ){P1ASF = 0x80; //Set P1.7 as input portADC_RES = 0; //Clear previous resultADC_RESL = 0;ADC_CONTR = ADC_POWER | ADC_SPEEDLL ;Delay(20); //ADC power-on delay and Start A/D conversion}/*---------------------------- LCD1602相应函数---------------------------*////////////////以下为LCD显示数据处理/////////////////void Num_to_Disp(uint i, uint Num){int xx, yy, zz;NUM = (Num * 4.68/ 1024.0); //计算公式:10-bit A/D Conversion Result = 1024 x (Vin / Vcc) NUM =NUM *29.1/9.9;xx = (int)NUM;yy = (int)((NUM - (float)(xx)) * 10);zz = (int)((NUM - (float)(xx)) * 100)%10;/********************第一行数字*******************************/pos_char_table[9]= data_char_table[i/100]; //输入值十位pos_char_table[10]= data_char_table[i%100/10]; //输入值个位pos_char_table[12]= data_char_table[i%10]; //输入值小数点后一位/********************第二行数字*******************************/num_char_table[9] = data_char_table[xx / 10]; //电压值十位num_char_table[10]= data_char_table[xx % 10]; //电压值个位num_char_table[12]= data_char_table[yy]; //电压值小数点后一位num_char_table[13]= data_char_table[zz]; //电压值小数点后两位}//////////////////以下为LCD显示////////////////////void LcdDisp(uint j, uint num){uint i=0;for (i=0;i<16;i++){lcd_char_write(i,0,Lcd_Dis1_table[i]);lcd_char_write(i,1,Lcd_Dis2_table[i]); //显示框架(固定文字)}Num_to_Disp(j, num);for(i = 9; i < 14; i++){lcd_char_write(i,0,pos_char_table[i]); //显示输入值}for(i = 9; i < 14; i++){lcd_char_write(i,1,num_char_table[i]); //显示电压}delay_1ms(100);}//////////////以下是LCD1602驱动程序////////////////void lcd_delay(uchar ms) /*LCD1602 延时*/{uchar j;while(ms--){for(j=0;j<250;j++){;}}}void lcd_busy_wait() /*LCD1602 忙等待*/{lcd_rs_port = 0;lcd_rw_port = 1;lcd_en_port = 1;lcd_data_port = 0xff;while (lcd_data_port&0x80);lcd_en_port = 0;}void lcd_command_write(uint command) /*LCD1602 命令字写入*/ {lcd_busy_wait();lcd_rs_port = 0;lcd_rw_port = 0;lcd_en_port = 0;lcd_data_port = command;lcd_en_port = 1;lcd_en_port = 0;}void lcd_system_reset() /*LCD1602 初始化*/{lcd_delay(20);lcd_command_write(0x38);lcd_delay(100);lcd_command_write(0x38);lcd_delay(50);lcd_command_write(0x38);lcd_delay(10);lcd_command_write(0x08);lcd_command_write(0x01);lcd_command_write(0x06);lcd_command_write(0x0c);}void lcd_char_write(uint x_pos,y_pos,lcd_dat) /*LCD1602 字符写入*/ {x_pos &= 0x0f; /* X位置范围0~15 */y_pos &= 0x01; /* Y位置范围0~ 1 */if(y_pos==1) x_pos += 0x40;x_pos += 0x80;lcd_command_write(x_pos);lcd_busy_wait();lcd_rs_port = 1;lcd_rw_port = 0;lcd_en_port = 0;lcd_data_port = lcd_dat;lcd_en_port = 1;lcd_en_port = 0;}void lcd_bad_check() /*LCD1602 坏点检查*/{char i,j;for(i=0;i<2;i++){for(j=0;j<16;j++) {lcd_char_write(j,i,0xff);}}lcd_delay(200);lcd_delay(200);lcd_delay(200);lcd_delay(100);lcd_delay(200);lcd_command_write(0x01); /* clear lcd disp */}//////////////////以上是LCD1602驱动程序/////////////////*----------------------------- 延时程序---------------------------*/ void Delay(uint n){uint x;while (n--){x = 500;while (x--);}}/*1MS为单位的延时程序*/void delay_1ms(uchar x){uchar j;while(x--){for(j=0;j<125;j++){;}}}void DelayMs(uchar ms) //延时程序{uint i;while(ms--){for(i = 0; i < 850; i++);}}void init_PWM(){CCON=0X00;CH=0;CL=0;CMOD=0X02; //0X00:以系统时钟/12 为时钟源,0X02:系统时钟/2,0x08:系统时钟PWM1_set(0X80);//起始占空比,0XC0:占空比为25%,0X80:占空比为50%,0X40:占空比为75% CCAPM1=0X42; //0X42:8位PWM P1.4输出,无中断;0X53:8位PWM输出,下降沿产生中断;0X63:上升沿产生中断;0X73:跳变沿产生中断CR=1; //计时器开始工作}void PWM1_set(uchar empty) //直接设置占空比{CCAP1L=empty;CCAP1H=empty;}void PWM1_change(uchar type,uchar change) //type=0减占空比,1增加占空比change: 0X0C约5%,0X05约2%{if(type==0){CCAP1L+=change;CCAP1H+=change;}else{CCAP1L-=change;CCAP1H-=change;}}void main(){init_PWM(); //初始化,PWM输出lcd_system_reset(); //LCD1602 初始化lcd_bad_check(); //LCD1602 坏点检查InitADC(); //初始化ADC特殊功能寄存器while(1) //按键增减PWM占空比{if(key1==0) //按键1按下{DelayMs(1); //按键消抖while(key1==0); //按键释放才跳出执行下一步ldata++; //显示数据加0.1}else if(key2==0) //按键2按下{DelayMs(1); //按键消抖while(key2==0); //按键释放才跳出执行下一步ldata--; //显示数据减0.1}else if(key3==0) //按键3按下{DelayMs(1); //按键消抖while(key3==0); //按键释放才跳出执行下一步ldata+=10; //显示数据加1}else if(key4==0) //按键4按下{DelayMs(1); //按键消抖while(key4==0); //按键释放才跳出执行下一步ldata-=10; //显示数据减1}else if(key5==0) //按键5按下{DelayMs(1); //按键消抖while(key5==0); //按键释放才跳出执行下一步ldata=0; //清0}LcdDisp(ldata,GetADCResult(7)); //液晶1602显示输入电压值和AD采集电压值(P1.7)NUM=10*NUM;show=ldata;if((NUM<(show-0.1))||(NUM>(show+0.1))){if(NUM<(show-0.1)){if((show-0.1)-NUM>1)PWM1_change(1,0X05);elsePWM1_change(1,0X01);}else{if(NUM-(show+0.1)>1)PWM1_change(0,0X05);elsePWM1_change(0,0X01);}Delay(500);}else{Delay(2000);}}}。
STC12C5A60S2两路AD采集用LCD1602显示#include#include#include "stdio.h"#define ulong unsigned long#define uint unsigned int#define uchar unsigned charuchar data adc _at_ 0x30;uchar data adc1 _at_ 0x31;sbit E=P2^7; //1602使能引脚sbit RW=P2^6; //1602读写引脚sbit RS=P2^5; //1602数据/命令选择引脚void SendByte(unsigned char dat);void SendStr(unsigned char *s);void L1602_string(uchar hang,uchar lie,uchar *p);void L1602_char(uchar hang,uchar lie,char sign);uchar AD();uchar AD1();void DelayUs2x(unsigned char t){while(--t);}/*------------------------------------------------mS延时函数,含有输入参数unsigned char t,无返回值unsigned char 是定义无符号字符变量,其值的范围是0~255 这里使用晶振12M,精确延时请使用汇编------------------------------------------------*/void DelayMs(unsigned char t){while(t--){//大致延时1mSDelayUs2x(245);DelayUs2x(245);}}void delay(){_nop_();_nop_();}void Delay(uint del){uint i,j;for(i=0;i<del;i++)< p="">for(j=0;j<=148;j++){}}/************************************************************** ******* 名称: bit Busy(void)* 功能: 这个是一个读状态函数,读出函数是否处在忙状态* 输入: 输入的命令值* 输出: 无*************************************************************** ********/ void Busy(void){bit busy_flag = 1;P0 = 0xff;RS = 0;delay();RW = 1;delay();E = 1;//Delay(1);while(1){busy_flag = (bit)(P0 & 0x80);if(busy_flag == 0){break;}}E = 0;}/************************************************************** ******* 名称: wcmd(uchar del)* 功能: 1602命令函数* 输入: 输入的命令值* 输出: 无*************************************************************** ********/ void wcmd(uchar del){RS = 0;delay();RW = 0;delay();E = 0;delay();P0 = del;delay();E = 1;delay();E = 0;}/************************************************************** ******* 名称: wdata(uchar del)* 功能: 1602写数据函数* 输入: 需要写入1602的数据* 输出: 无*************************************************************** ********/void wdata(uchar del){delay();RS = 1;delay();RW = 0;delay();E = 0;delay();P0 = del;delay();E = 1;delay();E = 0;}/************************************************************** ******* 名称: L1602_init()* 功能: 1602初始化,请参考1602的资料* 输入: 无* 输出: 无*************************************************************** ********/ void L1602_init(void){Delay(15);wcmd(0x38);Delay(5);wcmd(0x38);Delay(5);wcmd(0x38);wcmd(0x38);Busy();wcmd(0x08);Busy();wcmd(0x01);Busy();wcmd(0x06);Busy();wcmd(0x0c);}/************************************************************** ******* 名称: L1602_char(uchar hang,uchar lie,char sign)* 功能: 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下L1602_char(1,5,'b')* 输入: 行,列,需要输入1602的数据* 输出: 无*************************************************************** ********/void L1602_char(uchar hang,uchar lie,char sign){uchar a;if(hang == 1){a = 0x80;}if(hang == 2){a = 0xc0;}a = a + lie - 1;Busy();wcmd(a);Busy();wdata(sign);}/************************************************************** ******* 名称: L1602_string(uchar hang,uchar lie,uchar *p)* 功能: 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下L1602_string(1,5,"ab cd ef;")* 输入: 行,列,需要输入1602的数据* 输出: 无*************************************************************** ********/ void L1602_string(uchar hang,uchar lie,uchar *p) {uchar a;if(hang == 1){a = 0x80;}if(hang == 2){a = 0xc0;}a = a + lie - 1;while(1){Busy();wcmd(a);Busy();wdata(*p);a++;p++;if((*p == '\0')||(a==0x90)||(a==0xd0)){break;}}}uchar AD(){ulong i;uchar star;ADC_CONTR|=0x80;for(i=0;i<10000;i++);P1ASF=0x01;ADC_CONTR|=0XE1;for(i=0;i<10000;i++); while(1){ADC_CONTR|=0x08; star=0;while(star==0){star=ADC_CONTR&0x10; }ADC_CONTR&=0x00; adc=ADC_RES;//adc<<=2;//adc+=ADC_RESL; return adc;}}uchar AD1(){ulong i;uchar star;ADC_CONTR|=0x80;for(i=0;i<10000;i++);P1ASF=0;ADC_CONTR|=0XE0;for(i=0;i<10000;i++);while(1){ADC_CONTR|=0x08;star=0;while(star==0){star=ADC_CONTR&0x10; }ADC_CONTR&=0x00;adc1=ADC_RES;// adc1<<=2;// adc1+=ADC_RESL; return adc1;}}void main(){float i,j;unsigned char a[16]; unsigned char b[16];L1602_init();while(1){{i=AD()*5/256;sprintf(a," DA1=%4.2f v",i); L1602_string(2,0,a); DelayMs(1);j=AD1()*5/256;sprintf(b," DC2=%4.2f v",j);L1602_string(1,0,b); }}}</del;i++)<>。
STC12C5A60S2系列单片机AD功能详解
作者:裴博宇
作者原本旨在对STC12C5A60S2(后文简称该单片机、12C单片机)系列单片机相对传统51内核单片机升级内容进行详细解析,和程序应用分析,但是由于时间原因只写到了AD的查询方式使用,抱歉了,如果有什么错误欢迎批评指正,但是申明本人是一个学生,文章也只适合于初学者,希望行业的老人不要骂的太狠。
本文以STC12C5A60S2系列单片机芯片手册为母本编写。
一、相关寄存器介绍
12C单片机自带8路10位AD,要使用他就必须明确其相关寄存器:
P1AS F寄存器
P1口模拟配置寄存器,地址:9DH,复位值:00H。
12C单片机的AD转换引脚与P1I/O口复用,P1ASF寄存器指定P1寄存器哪一位用于AD 转换,哪一位做I/O口用。
具体是,P1ASF寄存器的8位对应P1的8位,1代表做AD转换通道用,0代表做I/O口用。
不可位寻址。
ADC_CONTR 寄存器
ADC控制寄存器,地址BCH,复位值:00H。
位说明:ADC_CONTR.7(这种写法其实是有问题的,因为该寄存器不支持位寻址,仅供阅读方便)——ADC_POWER。
ADC开关,要使用AD转换功能该位必须置“1”。
开
在初始化时直接将其置“1”,但考虑到能耗的因素,最好在使用时开启,使用结
束后关闭。
ADC_CONTR.6——SPEED1、ADC_CONTR.5——SPEED2,AD转换速率控制寄存器。
00——540个时钟周期转换一次;01——360个时钟周期转换一次;10——180个
时钟周期转换一次;11——90个时钟周期转换一次。
转换速率并非越快越好,当
然从效率角度来讲我们希望他更快,但是转换速率愉快能耗越高,同时准确度越
低,所以请选择一个合理的周期。
ADC_CONTR.5——FLAG,AD转换结束标志位。
当AD转换结束时,自动拉高,标
志转换结束。
注意,需用软件拉低。
ADC_CONTR.4——SRART,AD转换启动位。
置“1”AD转换启动。
ADC_CONTR.3-0——CHS2-0,表示对哪一个引脚的输入值进行AD转换,使用BCD
码,如下图
ADC_RES,ADC_RESL,AUXR1寄存器
ADC_RES AD转换结果储存高位寄存器,地址:BDH,复位值:00H。
ADC_RESL AD转换结果储存低位寄存器,地址:BEH,复位值:00H。
AUXR1 辅助寄存器,地址:A2H,复位值:00H。
当AUXR1.2——ADRJ 为0时,AD转换结果的高8位存放在ADC_RES中,低2位存放ADC_RESL的低2位中。
当ADRJ 为1时,AD转换结果的高2位存放在ADC_RES的低2位中,低8位存放在ADC_RESL 中。
PS:后文程序中不会出现AUXR1寄存器,使用第一种情况。
IE寄存器
中断允许寄存器,地址A8H,复位值00H。
相信大家对这个寄存器一定非常熟悉,在传统51中第7位为EA,第6位没有使用,12C 单片机的6位就是AD中断允许位。
这个就不多说了。
IP、IPH寄存器
IP:中断优先级设置寄存器低,地址:B8H,复位值00H。
IPH:中断优先级设置寄存器高,地址:B7H,复位值00H。
IP.5和IPH.5位AD中断优先级控制位
当PADCH=0且PADC=0时,A/D转换中断为最低优先级中断(优先级0)
当PADCH=0且PADC=1时,A/D转换中断为较低优先级中断(优先级1)
当PADCH=1且PADC=0时,A/D转换中断为较高优先级中断(优先级2)
当PADCH=1且PADC=1时,A/D转换中断为最高优先级中断(优先级3)
可位寻址和不可位寻址说明
以上内容几乎没有提及那些寄存器可位寻址,那些寄存器不可位寻址,现在做以说明。
可位寻址的寄存器(仅指上面提到的寄存器)包括IE和IP,其他均不可位寻址,也就是说只有传统51有的寄存器才可以位寻址,但是在使用C编写程序是,由于我们调用的是reg51的头文件,并且在预编译阶段只使用srf语句定义了寄存器,没有使用sbit语句定义位,所以程序的位操作,均使用“|”和“&”。
二、C语言程序编写说明(查询方式)
从上文可以看出12C单片机为AD设置了中断,但是我们为什么不用中断呢?(之后纯属个人看法)在我看来没有使用中断的必要,因为AD转换所用的时间并不长,完全可以让程序在这个地方等一段时间,用到中断后势必会影响其他的中断,涉及中断优先级和嵌套的问题,但是如果你使用数码管或者点阵做显示,或者说其他的什么原因,使得你认为这些时间对你来
说很重要,那么今后有缘再写吧。
程序预编译
#include "reg51.h"
#include "intrins.h" //使用_nop_();函数
#define _nop_() nop
/*定义相关特殊功能寄存器*/
sfr ADC_CONTR = 0xBC; //ADC control register
sfr ADC_RES = 0xBD; //ADC hight 8-bit result register
sfr ADC_LOW2 = 0xBE; //ADC low 2-bit result register
sfr P1ASF = 0x9D; //P1 secondary function control register
/*由于12C单片机不支持AD相关寄存器的位寻址,需使用“|”对寄存器执行位,故定义一下内容*/
/*“|”说明,之后不再提到X指未知量0x80=1000 0000B 0xXX | 0x80 = 1XXX XXXXB*/ /*“&”说明,0xEF=0111 1111B 0xXX & 0xEF=0XXX XXXXB*/
#define ADC_POWER 0x80 //ADC power control bit
#define ADC_FLAG 0x10 //ADC complete flag
#define ADC_START 0x08 //ADC start control bit
#define ADC_SPEEDLL 0x00 //540 clocks
#define ADC_SPEEDL 0x20 //360 clocks
#define ADC_SPEEDH 0x40 //180 clocks
#define ADC_SPEEDHH 0x60 //90 clocks
AD的初始化
void InitADC( )
{
P1ASF = 0xff; //Set all P1 as analog input port 0xff=1111 1111B 即P1全部用作AD,使用时根据实际情况赋值
ADC_RES = 0; //清空转换结果存储寄存器
ADC_RESL=0;
ADC_CONTR = 0x00;
nop; nop; nop; nop; //等待ADC_CONTR值写入
}
AD转换函数的编写
AD转换函数编写时,我们设计函数返回值为转换结果,函数参数包括要转换的引脚、转换速率,如果全部程序AD转换速率不变,可直接将speed的值在初始化时写入,如下。
unsigned int GetADC(unsigned char ch,unsigned char speed)
{
unsigned int res;
ADC_CONTR =ADC_CONTR | ADC_POWER | speed | ADC_START | ch;
nop; nop; nop; nop;//确保ADC_CONTR的值写入
while(!(ADC_CONTR & 0x10)); //如果AD转换未结束FLAG位为0,程序在此等待,如果为1,跳出循环
res=ADC_RES*4+ADC_RESL; //读AD转换结果,公式自己理解
ADC_RES=0;
ADC_RESL=0;
ADC_CONRT=0; //寄存器复位
return res;
}
有了这些我相信就够写一个程序了吧,但是注意这个地方还差点东西,缺一个滤波的过程,当然初学者如果对精度要求不高可以忽略这个,如果有兴趣可以去了解一下软件滤波。