第一篇:STC单片机通用AD转换程序
福星电子网http://
#include
#include
sfr P1_ADC_EN = 0x97;//A/D转换功能允许寄存器
sfr ADC_CONTR = 0xC5;//A/D转换控制寄存器
sfr ADC_DATA = 0xC6;//A/D转换结果寄存器 高8位,sfr ADC_LOW2 = 0xC7;//A/D转换结果寄存器 低2位,如果是8位AD无此寄存器。
#define uchar unsigned char;
#define uint unsigned int;
Uintad_out1,ad_out2;
void delay(uchar delay_time)// 延时函数
{
uchar n;
uint m;
for(n=0;n { for(m=0;m<10000;m++); } } uchar get_AD_result(uchar channel) { uchar AD_finished = 0;// 存储 A/D 转换标志 ADC_DATA = 0; ADC_CONTR = channel;// 选择 A/D 当前通道 _nop_();_nop_();_nop_();//使输入电压达到稳定 _nop_();_nop_();_nop_(); ADC_CONTR |= 0x08;//0000,1000 令 ADC_START = 1, 启动A/D 转换 AD_finished = 0; while(AD_finished == 0)// 等待A/D 转换结束 { AD_finished =(ADC_CONTR & 0x10);//0001,0000, ADC_FLAG ==1测试A/D转换结束否 } ADC_CONTR &= 0xF7;//1111,0111 令 ADC_START = 0, 关闭A/D 转换,return(ADC_DATA);// 返回 A/D 转换结果 } void main() { P1 = P1 | 0x01;// 0000,0001,P1.0为 A/D 转换,即通道0与1 福星电子网http:// P1_ADC_EN = 0x01;//0000,0001, P1 的P1.0设置为 A/D 转换输入脚// 断开P1.0,P1.1 内部上拉电阻 while(1) { get_AD_result(0); delay(10); //可以多采集几次求均值 //8位数据输出,参考电压5V ad_out1=(ADC_DATA*5)/256 //8位数据输出,参考电压5V ad_out2=((ADC_DATA*4)+ ADC_LOW2)/1024 } } 第九章 数模/模数转换电路 一、概念 1、信号分类:时间连续、数值连续的信号(模拟信号) 时间连续、数值离散的信号 时间离散、数值连续的信号 时间离散、数值离散的信号(数字信号) 2、典型的模拟信号处理系统由三部分组成: (1)模数转换器、(2)数字信号处理器、(3)数模转换器。 3、模数转换器将待处理的模拟信号转换成数字信号; 数字信号处理器对转换过来的数字信号进行处理,得到数字的处理结果; 数模转换器将处理结果转换成模拟信号。 二、D/A转换器 1、D/A转换器功能:将数字量成正比地转换成模拟量 D/A转换器由电阻网络、模拟电子开关及求和运算放大器 3、权电阻网络数模转换器 然而,位权电阻网络数模转换器包含种电阻,要在比较大的阻值范围内保证每个电阻都有很高的精度是十分困难的,尤其对制造集成电路不利。虽然双级权电阻网络数模转换器[图9.2.2] 所用的电阻种类减少了一倍,但是并没有质的变化。由于构思巧妙,倒T形权电阻网络数模转换器[图9.2.3] 所用的电阻种类只有两种,10位数模转换器AD7520就是一种倒T形权电阻网络数模转换器。为灵活起见,AD7520没有包含运算放大器,使用时需要外接。目前单片集成数模转换器多采用权电流型或开关电容型结构。理想情况下,位数模转换器的输出电压正比于输入的数字量,即数字量,果,其中,为输出的模拟电压,为输入的为参考电压。显然,如果为正,则为负;反之,如为负,则为正。如果需要具有双极性输出电压的数模转换器,为正)或负的(如果我们只需添加一个电阻和一个正的(如果为负)直流电压源,使运算放大器称为加法器即可[图9.2.15]。 为了保证信号处理结果的准确性,数模转换器必须有足够的精度。数模转换器在理论上可以达到的精度常用分辨率来表示,例如,12位数模转换器的精度比8位数模转换器的精度高得多,16位数模转换器的精度比12位数模转换器的精度高得多,等等。数模转换器实际上可以达到的精度用转换误差来表示。例如,转换误差为1/2LSB(最低有效位)的数模转换器的精度比转换误差为1LSB的数模转换器的精度高。为了保证信号处理结果的时效性,数模转换器必须有足够的转换速度。通常用建立时间来表示数模转换器的转换速度。在对转换速度要求不太高的场合,有时采用串行输入的数模转换器,以便减少传输线的数目。这种模数转换器由并行输入的数模转换器和移位寄存器构成,其中一位寄存器可以将串行的数字信号转换为并行的数字信号,供并行输入的数模转换器使用。 二、A/D转换器 1、模数转换的过程有四个阶段,即采样、保持、量化和编码。1)采样是将连续时间信号变成离散时间信号的过程。经过采样,时间连续、数值连续的模拟信号就变成了时间离散、数值连续的信号,称为采样信号。采样电路相当于一个模拟开关,模拟开关周期性地工作。理论上,每个周期内,模拟开关的闭合时间趋近于0。在模拟开关闭合的时刻(采样时刻),我们就“采”到模拟信号的一个“样本”。2)量化是将连续数值信号变成离散数值信号的过程。理论上,经过量化,我们就可以将时间离散、数值连续的采样信号变成时间离散、数值离散的数字信号。 我们知道,在电路中,数字量通常用二进制代码表示。因此,量化电路的后面有一个编码电路,将数字信号的数值转换成二进制代码。3)然而,量化和编码总是需要一定时间才能完成,所以,量化电路的前面还要有一个保持电路。保持是将时间离散、数值连续的信号变成时间连续、数值离散信号的过程。在量化和编码期间,保持电路相当于一个恒压源,它将采样时刻的信号电压“保持”在量化器的输入端。虽然逻辑上保持器是一个独立的单元,但是,工程上保持器总是与采样器做在一起。两者合称采样保持器。 2、模数转换器有直接型和间接型两种。 STC单片机串口在线烧录芯片问题总结 在一个偶然和朋友聊天中了解了STC单片机芯片,从此一发不可收拾。当时我看中STC芯片的一个主要原因是因为它有AD转换功能和在线烧录功能。用到现在算起来也大致有三、四年的时间了,在此期间用了不少STC不同型号的芯片。总的来讲这个芯片还是比较好使的,但在烧录过程中也碰到不少麻烦,现在把它罗列如下,以便和同行们一起交流、探讨和学习。 第一种情况是通过USB转串口烧录。曾经成功过一段时间,但后来不知道为什么再也烧录不进去了,直到现在也不明白其中的道理。查了一些资料说是USB转串口的芯片问题,需要专用芯片的USB转串口。我也信了,但从此给我的印象是-------STC单片机烧录程序时是要挑芯片的。 第二种情况是串口烧录时有些232芯片不好用,一打听才知道是232芯片不好,不能用国产的要用进口的,我又专门去买了一批7元多一片的进口232芯片,结果-------没有成功过。不得已只好换回用国产的,哎!好了,谢天谢地!阿弥多佛!看来STC芯片串口在线烧录不但挑USB转串口的芯片,还挑232芯片。 第三种情况是同一批板子、同一批232芯片有些板子能在线烧录程序,而有些板子却不能烧录程序,实在没办法。还好本次产品是采用PLCC封装的,只好把不能烧录的芯片拔到可以烧录的板子上去烧录好再拔插回去,说到这里有人可能会怀疑不能烧录的板子232芯片或外围电路有问题,我当时的直觉也是这样的,但是我板子232口只要烧录好程序,工作时通讯一切正常,这又作何解释?不可思议! 第四种情况(也是我偶然发现的)5v的STC15F104E芯片,有时候能烧录,有时候不能烧录,不能烧录的概率在90%以上,真是莫名其妙。摸索了将近一天时间才发现串口接上后(板子在没有上电的时候)STC芯片电源脚有约3v电压,我想想可能是从串口反串回来的,有这3v电压的存在,芯片就如同没有掉电,所以也就烧录不进去。我就用镊子把电源到地短接一下,目的是进行放电。然后马上给板子上电,哎~~~成了!并且屡试不爽。有类似情况的朋友也不妨一试。哈。。 第五种情况是我有一批板子用的是STC12LE5A60S2 QFP44封装,在我的笔记本上用串口烧录成功率为100%,而到我台式机上用串口烧录时成功率却为0%,是我台机的串口有问题吗?非也!台机串口烧录STC15F104E和其它是好的,但是对付本批次板却是无计可施,最后无论我如何绞尽脑汁也不得其解,只好怀疑是板子在设计时有问题,但是设计有问题的板子为什么在笔记本上烧录又是好的呢?只能说-------STC芯片串口在线烧录不但挑USB转串口的芯片、挑232芯片,还挑电脑。 第六种情况是同一块板子今天能烧录进去,过一段时间又烧录不进去了,再放一段时间又能烧录进去了。唉~~~看来STC芯片串口在线烧录不但挑USB转串口的芯片、挑232芯片、挑电脑,还要看它的心情。 我晕!STC的芯片真的是让人欢喜让人忧。 SECOND EQU 40H ;给内存RAM空间中40H单元起名SECOND MINUTE EQU 41H ;给内存RAM空间中41H单元起名MINUTE HOUR EQU 42H ;给内存RAM空间中42H单元起名HOUR SECONDGEWEI EQU 43H ;给43H单元起名SECONDGEWEI存秒的个位 SECONDSHIWEI EQU 44H ;给44H单元起名SECONDSHIWEI存秒的十位 MINUTEGEWEI EQU 45H ;给45H单元起名MINUTEGEWEI存分的个位 MINUTESHIWEI EQU 46H ;给46H单元起名MINUTESHIWEI存分的十位 HOURGEWEI EQU 47H ;给47H单元起名HOURGEWEI存小时的个位 HOURSHIWEI EQU 48H ;给48H单元起名HOURSHIWEI存小时的十位 ORG 0000H ;复位时程序从此开始 SJMP START ;跳到START进行初始化 ORG 000BH ;定时器 0中断入口 AJMP TIMER0 ;跳转到TIMER0处 ORG 0030H ;初始化程序从30H开始;---------------初始化START------------------------------START: MOV SECOND, #0 ;给秒存储单元SECOND赋初始值0 MOV MINUTE, #0 ;给分存储单元MINUTE赋初始值0 MOV HOUR , #12 ;给小时存储单元HOUR赋初始值12 MOV DPTR , #TAB ;给数据指针赋值,将DPTR指向TAB数据表头处 MOV 30H, #0 ;给30H单元赋初始值0(用于计20次的50ms中断)MOV TH0,#3CH ;给计数容器的高8位TH0赋初始值3CH MOV TL0,#0B0H ;给计数容器的低8位TL0赋初始值B0H MOV TMOD,#00000001B ;C/T位设置为0,M1M0设置位10,即模式1定时 MOV TCON,#00010000B ;TR0设置为1,即启动定时器0开始工作 SETB ET0 ;IE中的ET0位设置为1,开定制器中断0 SETB EA ;IE中的EA位设置为1,开总中断;-----------------------主程序MAIN-----------------------------MAIN:CALL KEY ;调按键子程序KEY CALL PROCESS ;调数据处理子程序PROCESS CALL DISPLAY ;调显示子程序DISPLAY SJMP MAIN ;跳转到MAIN标号处;------------------------------按键子程序KEY调时-------------------KEY:MOV P1,#0FEH ;行扫描 LCALL DELAY ;JNB P1.4,HOURJIA ;P1.4引脚如果是低电平就跳到HOURJIA处 JNB P1.5,HOURJIAN ;P1.5引脚如果是低电平就跳到HOURJIAN处 JNB P1.6,MINUTEJIA ;P1.6引脚如果是低电平就跳到MIMUTEJIA处 JNB P1.7,MINUTEJIAN ;P1.7引脚如果是低电平就跳到MIMUTEJIAN处 FANHUI:RET ;子程序返回(如果没有按键按下) HOURJIA:CALL DELAY ;调延时程序目的是跳过按键抖动期(去抖)JB P1.4,FANHUI ;P1.4如果是高电平就跳到FANHUI处(没键按)JNB P1.4,$ ;如果P1.4是低电平就停在当前位置等键释放 MOV R4,HOUR CJNE R4,#23,A1 ;判断时数字是否为23 AJMP A2 A1:INC HOUR ;把小时位加1 MOV SECOND, #0 ;小时进位,秒归0 RET A2:MOV HOUR,#0 ;小时数为23时加一为0 MOV SECOND, #0 ;小时进位,秒归0 RET ;子程序返回 HOURJIAN:CALL DELAY ;调延时程序目的是跳过按键抖动期(去抖)JB P1.5,FANHUI JNB P1.5,$ MOV R5,HOUR CJNE R5,#0,A3 AJMP A4 A3:DEC HOUR MOV SECOND, #0 RET A4:MOV HOUR,#23 MOV SECOND, #0 RET MINUTEJIA:CALL DELAY JB P1.6,FANHUI JNB P1.6,$ MOV R6,MINUTE CJNE R6,#59,A5 AJMP A6 A5:INC MINUTE MOV SECOND, #0 RET A6:MOV SECOND, #0 MOV MINUTE, #0 MOV R4,HOUR CJNE R4,#23,A10 MOV HOUR,#0 RET A10:INC HOUR RET MINUTEJIAN:CALL DELAY JB P1.7,FANHUI JNB P1.7,$ MOV R7,MINUTE CJNE R7,#0,A7 AJMP A8 A7:DEC MINUTE ;P1.5如果是高电平就跳到FANHUI处(没键按) ;如果P1.5是低电平就停在当前位置等键释放 ;判断时数字是否为23 ;把小时位减1 ;小时数为0时减一为23 ;子程序返回 ;调延时程序目的是跳过按键抖动期(去抖) ;P1.6如果是高电平就跳到FANHUI处(没键按) ;如果P1.6是低电平就停在当前位置等键释放 ;判断分钟数是否为59 ;把分钟位加1 ;给秒存储单元SECOND赋初始值0 ;分钟数为59则分钟归0 ;判断时数字是否为23 ;23时增1归0 ;分钟数为59 自增1后小时增1 ;子程序返回 ;调延时程序目的是跳过按键抖动期(去抖) ;P1.7如果是高电平就跳到FANHUI处(没键按) ;如果P1.7是低电平就停在当前位置等键释放 ;判断分钟数是否为0 ;分钟不为0把分钟位减1 MOV SECOND, #0 RET A8:MOV MINUTE, #59 ;分钟数为0时减一为59 MOV R4,HOUR CJNE R4,#0,A9 ;判断时钟数是否为0 MOV HOUR,#23 ;时钟数为0减1为23 MOV SECOND, #0 RET A9:DEC HOUR ;时钟数不为0则减1 MOV SECOND, #0 RET ;子程序返回;-------------------处理子程序PROCESS-----------------------PROCESS:MOV A, SECOND ;把SECOND中的秒值拷贝给A MOV B, #10 ;给寄存器B赋值10 DIV AB ;A除以B,结果存入A中,余数存入B中 MOV SECONDSHIWEI , A ;结果即秒的十位数拷贝给SECONDSHIWEI MOV SECONDGEWEI , B ;余数即秒的个位拷贝给SECONDGEWEI MOV A, MINUTE ;把MINUTE中的分值拷贝给A MOV B, #10 ;给寄存器B赋值10 DIV AB ;A除以B,结果存入A中,余数存入B中 MOV MINUTESHIWEI , A ;结果即分的十位拷贝给MINUTESHIWEI MOV MINUTEGEWEI , B ;余数即分的个位拷贝给MINUTEGEWEI MOV A, HOUR ;把HOUR中的小时值拷贝给A MOV B, #10 ;给寄存器B赋值10 DIV AB ;A除以B,结果存入A中,余数存入B中 MOV HOURSHIWEI , A ;结果即小时的十位拷贝给HOURSHIWEI MOV HOURGEWEI , B ;余数即小时的个位拷贝给HOURGEWEI RET ;子程序结束返回到主程序;-----------------显示子程序DISPLAY--------------DISPLAY:MOV A, HOURSHIWEI ;小时的十位拷贝给A MOVC A, @A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(小时的十位)送到P0 CLR P2.0 ;将P2.0置低电平,对应的三极管导通 CALL DELAY ;调延时(让显示小时十位的数码管持续亮一段时间)SETB P2.0 ;将P2.0置高电平,对应三极管截止,对应数码管灭 MOV A, HOURGEWEI ;小时的个位拷贝给A MOVC A,@A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(小时的个位)送到P0 CLR P2.1 ;将P2.1置低电平,对应的三极管导通 CALL DELAY ;调延时(让显示小时个位的数码管持续亮一段时间)SETB P2.1 MOV P0,#7FH CLR P2.1 CALL DELAY SETB P2.1 ;将P2.1置高电平,对应三极管截止,对应数码管灭 MOV A, MINUTESHIWEI ;分钟的十位拷贝给A MOVC A,@A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(分钟的十位)送到P0 CLR P2.2 ;将P2.2置低电平,对应的三极管导通 CALL DELAY ;调延时(让显示分钟十位的数码管持续亮一段时间)SETB P2.2 ;将P2.2置高电平,对应三极管截止,对应数码管灭 MOV A, MINUTEGEWEI ;分钟的个位拷贝给A MOVC A,@A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(分钟的个位)送到P0 CLR P2.3 ;将P2.3置低电平,对应的三极管导通 CALL DELAY ;调延时(让显示分钟个位的数码管持续亮一段时间)SETB P2.3 ;将P2.3置高电平,对应三极管截止,对应数码管灭 MOV P0,#7FH CLR P2.3 CALL DELAY SETB P2.3 MOV A, SECONDSHIWEI ;秒的十位拷贝给A MOVC A,@A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(秒钟的十位)送到P0 CLR P2.4 ;将P2.4置低电平,对应的三极管导通 CALL DELAY ;调延时(让显示秒钟十位的数码管持续亮一段时间)SETB P2.4 ;将P2.4置高电平,对应三极管截止,对应数码管灭 MOV A, SECONDGEWEI ;秒的个位拷贝给A MOVC A,@A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(秒钟的个位)送到P0 CLR P2.5 ;将P2.5置低电平,对应的三极管导通 CALL DELAY ;调延时(让显示秒钟个位的数码管持续亮一段时间)SETB P2.5 ;将P2.5置高电平,对应三极管截止,对应数码管灭 RET ;显示子程序结束返回主程序;--------------------中断服务子程序----------------------------TIMER0:MOV R3, A ;把A中的数据送入R3保护起来 INC 30H ;30H单元中的数加1 MOV A, 30H ;30H单元中的数据拷贝给A CJNE A,#20,JIXU ;A中的数据与20比较不相等就跳转到JIXU处 MOV 30H,#0 ;(如果30H单元计满20了)给30H赋值0 INC SECOND ;把SECOND中的秒钟数加1 MOV A,SECOND ;把SECOND中的数据拷贝给A CJNE A, #60, JIXU ;A中的数据与60比较不相等就跳转到JIXU处 MOV SECOND, #0 ;给秒SECOND赋值0 INC MINUTE ;把MINUTE中的分钟数加1 MOV A, MINUTE ;把MINUTE中的数据拷贝给A CJNE A, #60, JIXU ;A中的数据与60比较不相等就跳转到JIXU处 MOV MINUTE, #0 ;给分钟MINUTE赋值0 INC HOUR ;把HOUR中的小时数据加1 MOV A, HOUR ;把HOUR中的数据拷贝给A CJNE A, #24, JIXU ;A中的数据与24比较不相等就跳转到JIXU处 MOV HOUR, #0 ;给小时HOUR赋值0 JIXU: MOV A,R3 ;把刚才送入R3中的数据还给A MOV TH0,#3CH ;给计数容器的高8位TH0赋初始值3CH MOV TL0,#0B0H ;给计数容器的低8位TL0赋初始值B0H RETI ;中断子程序返回主程序;---------------------------延时子程序----------------------------DELAY:MOV R0, #50 ;给R0赋值50 D2:MOV R1, #10 ;给R1赋值10 D1:DJNZ R1, D1 ;R1减1不等于0跳到D1处 DJNZ R0, D2 ;R0减1不等于0跳到D2处 RET ;延时子程序结束返回调用该程序的下一条;---------------下面的数据表中存储的是显示段码(共阳)-------------------TAB:DB 0C0H,0F9H,0A4H,0B0H,99H ;从TAB处开始存储0、1、2、3、4 DB 92H ,82H ,0F8H,80H ,90H ;5、6、7、8、9对应的显示段码 END ;程序结束 51单片机舵机程序不用定时器:自己整理的不用定时器调舵机向左,中,右三个方向摆动的51单片机程序 #include for(y=110;y>0;y--);} void delayus2x(unsigned char t){ while(--t);} void delay750us(){ delayus2x(245);delayus2x(122);} void delay1500us(){ delayus2x(245); delayus2x(245); delayus2x(245);} void delay2300us(){ delayus2x(245); delayus2x(245); delayus2x(245); delayus2x(245); delayus2x(147); } void main() //a=~a和delay顺序不能反 { while(1){ uint i=50;while(--i) //中 { a=1; delay1500us(); a=0; delay(20); } i=50; while(--i) { a=1; delay2300us(); a=0; delay(20); } i=50; while(--i) { a=1; delay750us(); a=0; delay(20); } } } //左 //右第二篇:第十章 AD转换电路教案
第三篇:STC单片机串口在线烧录芯片问题总结
第四篇:89C51单片机时钟程序
第五篇:51单片机舵机程序