| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 嵌入式 -> 郭天祥的10天学会51单片机_第六节 -> 正文阅读 |
|
[嵌入式]郭天祥的10天学会51单片机_第六节 |
全局变量:该变量在主函数外面定义 局部变量:在函数体内部定义 当子函数内部定义的变量,该变量的变量名和全局变量名相同并且类型相同时,在主函数调用该子函数时,该子函数的该变量有效,将全局变量屏蔽掉 D/A,数字量(Digital):例如直接从5V跳到0V;模拟量(Anolog):例如从5V缓慢变化到0V,有个变化的过程。 例子:1111 1111??? 对应??? 5v(或50mA) 1000 0000??? 对应??? 2.5v(或25mA) 0000 0000??? 对应??? 0v(或0mA) 当都接0时,从最右边的电阻依次并联算起,到最左边的2R电阻处再和右边全部的电阻(并联后也为2R)为R,所以Vref/R= I, Io2=1/2 I,Io1=0 当I7接0,其它接1时,I7处的电流为I7,I7右边的电流也为I7,所以Io2=1/2 I 当I7接1,当I6接1,先不看其它支路,Io1=(1/2 )*Vref/R+(1/2 *1/2 ) *Vref/R 以此类推,到最后全接1时Io1=Vref/R(1/2+1/2*1/2+……+1/2的八次方) DAC0832,这里用直通方式,一种简单的方式会了其它方式照猫画虎就行 ?Vref为输入参考电压,这里IOUT2接地,IOUT1作为输出,当需要模拟电压时IOUT1接运算放大器并且连接Rfb(反馈电阻) 类似这样上面有横杠的表示低电平有效;上图中连线上连接与门的圆圈表示取反? CS表示片选信号,Chip Select 下载数据文档:Datasheet即数据文档网站:www.21ic.com-->左边的IC处填写”DAC0832”,“资料”-->下载Datasheet。www.alldatasheet.com 看资料芯片看串并行方式,接口说明,转换位数和转换速率,操作时序 www.maxim-ic.com,如果是并行的一次把数据都读走,但浪费I/O口 见dac0832资料,P5图,ts指不稳定的输出范围,之后稳定 选取DA时,要先知道设计的产品的运行速度,然后选取DA的转换速率,根据产品的精度选取DA的精度即位 串行MAX531的资料:DIN是数据输入端,SCLK是数据时钟,DOUT是输入电压,VDD是电源,VOUT是输出电压,REFIN是参考电压,AGND是接地 时序图中,网格表示无所谓高低电平,两个箭头包起来的数据表示有效数据,MAX531的资料P8中图Figure1:SCLK上升沿读走位(DIN)的数据,八个上升沿就读走八个位数据。 看这种资料主要看各个管脚怎么使用以及时序图 时序图中,阴影表示高低电平都可以;两个箭头包起来的数据表示有效数据,例如DIN SCLK上升沿读走位(DIN)的数据,八个上升沿就读走八个位数据 DA资料中,看多少位,速度,管脚,时序图,有的接法不同,时序图就不同 找资料,根据资料设计电路,按资料上的器件接法连接,把资料上的电器件(如电阻的阻值,电容的法拉)都表示清楚,然后画Protel图,再做出PCB板子,拿到车间生产焊接再连接单片机就制作出来了。 见dac0832的PDF的P5,图中表示CS和ILE要先给低电平,然后WR给低电平,随后有效数据就传送过去,经过一小段时间稳定一下,IOUT1和IOUT2再进行有效输出 直通连接方式:直接送数据,IOUT1口就输出;结合TX-1C原理图看,赋给相应管脚低电平或高电平,结合DA接口.bmp看,DI0到DI7是数据口连接单片机的P0口,其它的为控制口或电源口,CSDA连接单片机的P3.2口(使用时要给低电平),WR连接单片机的P3.6口(使用时要给低电平);IOUT1口输出的P5的2和3用跳线帽(又叫短路子)短路,IOUT1输出的电流直接穿过发光二极管到地上,输出的数字量变化,那么输出的模拟量就变化,模拟量的变化体现在流过发光二极管上的电流,发光二极管就有明暗的变化可以判断有没有把DA操作起来,1口可以外接运算放大器;DA输出口的器件,当2和3短路后直接通过发光二极管接地 和赋给低电平 输出最高电压,点亮DA的灯,一上电P0口到P3口就输出最大值,所以开始DA的灯就亮: #include<reg52.h> sbit csda=P3^2;//注意csda(数模)和csad(模数)相区别 sbit wr=P3^6; void main() { ?????? csda=0; ?????? wr=0; ?????? P0=0xff;//输出最高电压,P0=0时,关闭DA灯 ?????? while(1); } 我的随笔程序:证明按照AD的时序图来操作是可以的,可以让片选CSDA高低电平变化,并且WR高低电平的变化: #include<reg52.h> #define uint unsigned int #define uchar unsigned char sbit csda=P3^2;//注意csda(数模)和csad(模数)相区别 sbit wr=P3^6; sbit dula=P2^6; sbit wela=P2^7; uchar aa; void delay(uint z) { ?????? uint x,y; ?????? for(x=z;x>0;x--) ????????????? for(y=110;y>0;y--); } void main() { ?????? while(1) ?????? { ????????????? dula=0; ????????????? wela=0; ????????????? aa++; ????????????? if(aa==256) ???????????????????? aa=0; ????????????? csda=0; ????????????? wr=0; ????????????? P0=aa;//输出最高电压,P0=0时,关闭DA灯 ????????????? delay(5); ????????????? wr=1; ????????????? csda=1; ????????????? delay(5); ?????? } } DA灯由灭到逐渐变到最亮,时间2s,由最亮到逐渐变暗到灭,时间2s 我的程序: #include<reg52.h> #define uint unsigned int #define uchar unsigned char sbit csda=P3^2; sbit wr=P3^6; sbit wela=P2^7; uchar flag; int aa,bb,cc; void init() { ?????? csda=0; ?????? wr=0; ?????? P0=0; ?????? TMOD=0x01; ?????? TH0=(65536-7812)/256; ?????? TL0=(65536-7812)%256; ?????? EA=1; ?????? ET0=1; ?????? TR0=1; ?????? wela=1; ?????? P0=0xff; ?????? wela=0; ?????? bb=255; } void main() { ?????? init(); ?????? while(1) ?????? { ????????????? P0=cc; ?????? } } void timer0() interrupt 1 { ?????? if(flag==0) ?????? { ????????????? TH0=(65536-7812)/256; ????????????? TL0=(65536-7812)%256; ????????????? aa++; ????????????? if(aa==256) ????????????? { ???????????????????? aa=0; ???????????????????? flag=1; ????????????? } ????????????? cc=aa; ?????? } ?????? if(flag==1) ?????? { ????????????? TH0=(65536-7812)/256; ????????????? TL0=(65536-7812)%256; ????????????? bb--; ????????????? if(bb==-1) ????????????? { ???????????????????? bb=255; ???????????????????? flag=0; ????????????? } ????????????? cc=bb; ?????? } } DA灯亮灭变化的同时发光二极管做加法变化: #include<reg51.h> sbit wela=P2^7; sbit dula=P2^6; sbit dawr=P3^6; sbit csda=P3^2; unsigned char a,j,k; void delay(unsigned char i) { ? for(j=i;j>0;j--) ??? for(k=125;k>0;k--); } void main() { ? wela=0; ? dula=0;//因为下面控制P1口,段选和位选给零,不让数码管干扰 ? csda=0; ? a=0; ? dawr=0; ? while(1) ? ??? { ?????? ? P0=a; ?????? ? P1=~a; ?????? ? delay(50); ?????? ? a++; } } A/D:例如把0到8V电压分成百位就是全部量化分配到0到255 用的最多的是逐次逼近式和双积分式 见PPT的P16:VIN模拟量的输入端,EOC(End Of Convert)转换结束(输出一个信号,告诉转换结束,可以把数据读走),倒三角是比较器,OE(Output Enable)是使能端,D/A转换器有A/D转换的功能 倒三角是比较器,倒三角上面的线(带圆圈的是上面)输出比下面高输出就是1,上面的线输出比下面低输出就是0;图中最右边,从右向左看,先将作为参考电压,这里将八位D/A转换器的最高位先置1,通过D/A转换器后的对应电压是?=?/2,输出电压为?=?/2,与?比较,如果大,则置1到N位寄存器最高位并传给D/A转换器,如果小,则置0到N位寄存器最高位并传给D/A转换器和锁存缓存器,再在D/A转换器的第二位置1,进行判断,如此类推,进行八次后,EOC口输出一个信号给单片机,告诉转换结束,单片机收到EOC信号后给OE一个低电平再将数据读走 见dac0832资料P1的典型管脚连线图,11到18管脚是数据口(TX-1C型单片机实验板原理图中的DB1到DB8),用来送数据,接单片机的P1口;INTR是中断口,当芯片转换完给单片机一个中断,要接单片机的外部中断(P3.2口或P3.3口),开发板中AD转换器没;使用中断,就是过段时间去读,肯定能转换完;RD和WR接单片机的RD和WR,即单片机的P3.6口和P3.7口;CS即片选,接锁存器(控制数码管位选的那个锁存器)的CSAD;VCC接5V电压;CLK R和CLK IN接管脚19和4是一个RC振荡电路,作用是提供频率让A/D转换;VIN(+)和VIN(-)采集电压,组成差分电路,输出差分信号,两条电路用来比较,可以采集桥式电路(见下图,可以做电子秤,上面的支路的第一个电阻是滑动电阻,两条并联的支路的两个电阻之间的导线连在VIN(+)和VIN(-)上,得到的压差来得出压力值);A GND表示模拟电压地端,D GND表示数字电压地端,之所以分开是防止它俩有干扰;Processor是处理器,即单片机(51,arm等);AD转换器在开发板中的电源灯下面,ADIN在AD转换器的左侧,即有跳线帽的,为了扩展,可能接模拟输入端,开发板中将其1和2短路,上面的滑动变阻器对应开发板中AD转换器的右边,可以调节上面的旋钮,ADIN的1连接着AD转换器的6管脚,6管脚下面的7管脚接地,所以6管脚就能检测到0到5伏之间的变化,ADIN的1管脚和AD转换器的6管脚之间的10k电阻是限流电阻,保护不被击穿,但电压是不会变的;AD转换器的9管脚是,?即,开发板上用两个1K电阻分成2.5V ?见P5的时序图,第一个图是开始转换,CS给低电平,WR在CS低电平期间给个低脉冲,即在CS给低电平之后稍过一段时间WR给个低脉冲,实际内部转换状态(Actual Internal Status Of The Converter)的BUSY表示AD转换过程,转换完INTR给个低电平通知中断,实际内部转换状态和INTR可以不用程序实现,只是表示转换过程;第二个图是读取数据,如果要AD转换器一直工作就让CS一直置0;中断INTR通知后,给RD一个低电平,在RD低电平到高电平变化的瞬间把数据读走,开发板上不用中断,所以不用考虑中断;程序中就让RD为高,变低,再为高,读走数据,即送到P1口;AD转换器的CSAD连接着锁存器,程序中直接控制锁存器就行 开发板中的AD转换器的数据口也连接着发光二极管,设计一个程序,就不停的启动读,数字量变化八个发光二极管就亮灭变化 ? 见ad0804的PDF的P18,是内部工作频率,八个数据全转换完需要八个,R=10K,C=145PF,由公式可得,开发板上的C很大,所以程序启动后要等一会再读数字 利用AD转换器动态显示发光二极管: #include<reg52.h> #define uchar unsigned char #define uint unsigned int sbit wr=P3^6; sbit rd=P3^7; void delay(uint z) { ?????? uint x,y; ?????? for(x=z;x>0;x--) ????????????? for(y=110;y>0;y--); } void init(); void start(); void main() { ?????? init(); ?????? while(1) ?????? { ????????????? start(); ????????????? delay(20); ????????????? rd=0;//rd低电平才能读数据,见时序图 ??????? delay(10);//一定要延时一会将数据读走再将rd变高电平,见上面的总结 ????????????? rd=1; //rd高电平为了下次变低电平后读数据 ????????????? delay(10); ?????? }???? } void init() { ?????? P0=0;//即将csad赋给0,A/D转换器被选用 } void start() { ?????? wr=1;//见0804的资料上的时序图,启动AD转换 ?????? wr=0; ?????? wr=1;????? } A/D转换器的数据口接在DB1到DB8上,DB1到DB8连在发光二极管上,所以A/D转换器的数据口有数据输出,发光二极管也会亮 旋转AD转换器右边的电位器的旋钮,发光二极管的亮度会变化。 TX-1C型单片机实验板原理图中单片机和数码管中间的是USB设备开发芯片,右边是USB下载接口,晶振下面是复位电路,复位电路下面是DS18B20是数字温度传感器,DS18B20下面是串口,串口那,电容处的104表示10*?PF(皮法),103是10*PF,180是18*;电阻4K7是4.7K,5R8是5.8欧姆;封装(电阻,电容封装方式):0805,还有1206封装,3216封装,0604封装,0302封装(数字越小封装越小);键盘下面的P6到P9是扩展口(下面标明了对应的P0、P1、P2和P3),即开发板上单片机左右的两排针;扩展口的右边是EEPROM,再右边是1602液晶接口,再右边是1280液晶接口;晶振右边是下载程序的指示灯,键盘上面是AD转换器 开发板上,黄色的是电容,黑色的是电阻 课件练习: 将AD模拟数字的模拟量读回来,转换成十进制数显示在数码管的前三位上,0到255: 我的程序: #include<reg52.h> #define uint unsigned int #define uchar unsigned char uchar bai,shi,ge,temp; sbit dula=P2^6; sbit wela=P2^7; sbit wr=P3^6; sbit rd=P3^7; uchar code table[]={ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71, 0x76,0x79,0x38,0x3f,0 }; void delay(uint z) { ?????? uint x,y; ?????? for(x=z;x>0;x--) ????????????? for(y=110;y>0;y--); } void start() { ?????? wela=1; ?????? P0=0; ?????? wr=0;//下面不能加延时程序delay(10),一旦加入延时,wela=1;P0=0;这两句就把数码管//打开,让八个数码管一起显示,而没有延时,刚打开数码管就wela=0关闭就不会出现八个//数码管一起显示 ?????? wr=1; ?????? P0=0xff; ?????? delay(10); ?????? wela=0; } void display(uchar aa,uchar bb,uchar cc) { ?????? dula=1; ?????? P0=table[aa]; ?????? dula=0; ?????? P0=0xff; ?????? wela=1; ?????? P0=0xfe; ?????? wela=0; ?????? delay(10); ?????? dula=1; ?????? P0=table[bb]; ?????? dula=0; ?????? P0=0xff; ?????? wela=1; ?????? P0=0xfd; ?????? wela=0; ?????? delay(10); ?????? dula=1; ?????? P0=table[cc]; ?????? dula=0; ?????? P0=0xff; ?????? wela=1; ?????? P0=0xfb; ?????? wela=0; ?????? delay(10); } void init() { ?????? P0=0; } void main() {???? ?????? init(); ?????? while(1) ?????? { ????????????? start(); ????????????? delay(20); ?????? ?????? wela=1;//必须有这句,否则会出错,现象是只显示255,因为上次存储器锁存的是//P0=0xff,如果不打开wela,锁存器仍然锁存0xff,而不会把新的P0值存入并显示 ????????????? P1=0xff; ????????????? P0=0; ????????????? rd=0; ????????????? temp=P1; ????????????? rd=1;????? ????????????? P0=0xff; ????????????? P1=temp; ????????????? delay(20); ????????????? display(temp/100,temp%100/10,temp%10);??????? ?????? } }???? 课件的程序: #include<reg51.h> #include <intrins.h> #define uint unsigned int #define uchar unsigned char sbit adrd=P3^7;????????????????????????? //IO口定义 sbit adwr=P3^6; sbit diola=P2^5; sbit dula=P2^6; sbit wela=P2^7; unsigned char j,k,adval; void delay(unsigned char i)????????? //延时程序 { ? for(j=i;j>0;j--) ??? for(k=125;k>0;k--); } uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,??????????????????????????? //数码管编码 ??????????????????????? 0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; void display(uchar bai_c,uchar sh_c,uchar g_c)???????????????? //显示程序 {? ?? P0=table[bai_c];???????????? //显示百位 ?? dula=1; ?? dula=0; ?? P0=0xfe; ?? wela=1; ?? wela=0; ?? delay(5); ?? dula=0; ?? P0=table[sh_c];??????? //显示十位 ?? dula=1; ?? dula=0; ?? wela=0; ?? P0=0xfd; ?? wela=1; ?? wela=0; ?? delay(5); ?? P0=table[g_c];???????? //显示个位 ?? dula=1; ?? dula=0; ?? P0=0xfb; ?? wela=1; ?? wela=0; ?? delay(5); } void main()?????????? //???? 主程序 { ? uchar a,A1,A2,A2t,A3; ??? while(1) ? ??? { ??? wela=1; ??? P0=0;?????????????????????? //选通ADCS ??? adwr=0;??????????????? //AD写入(随便写个什么都行,主要是为了启动AD转换) ??? _nop_(); ??? adwr=1; ??? P0=0xff;??????????????????? //关闭ADCS ??? delay(10); wela=0;???????????????????? //关闭有AD片选信号锁存器的锁存端以防止在操作数 //码管时使AD的片选发生变化 ?????? for(a=20;a>0;a--)??????? //需要注意的是ADC0804在写和读之间的时间间隔要足够//长否则无法读出数据 ??? {?????????????????????????? //这里把显示部分放这里的原因也是为了增加写读之间//的时间间隔??????????????????????????? ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??????? display(A1,A2,A3); ???? }??? //送去显示各位。 ???? wela=1;??????? ???????????//重新打开有AD片选信号锁存器的锁存端 ???? P1=0xff;??????????????????? //读取P1口之前先给其写全1 ???? P0=0;?????????????????????? //选通ADCS ???? adrd=0;???????????????????? //AD读使能 ???? adval=P1;?????????????????? //AD数据读取赋给P1口 ???? adrd=1; ???? P0=0xff;???????????????????? //关闭ADCS ???? adwr=0; ???? P1=adval;??????????????????? //同时把AD的值送八个发光二极显示 ???? A1=adval/100;??????????? //分出百,十,和个位 ???? A2t=adval%100; ???? A2=A2t/10; ???? A3=A2t%10; ?? }; }???? 将AD的值读回来,赋给DA,即调节AD的电位器时,DA对应的发光二极管也会发生变化: 我的程序: #include<reg52.h> #define uint unsigned int #define uchar unsigned char sbit adwr=P3^6; sbit adrd=P3^7; sbit dula=P2^6; sbit wela=P2^7; sbit csda=P3^2; uchar temp; void delay(uchar z) { ?????? uchar x,y; ?????? for(x=z;x>0;x--) ????????????? for(y=110;y>0;y--); } void init() { ?????? temp=0; ?????? P0=0; } void start() { ?????? P0=0; ?????? adwr=0; ?????? adwr=1; ?????? P0=0xff; } void admode() { ?????? csda=0;?? ?????? adwr=0; ?????? //temp=P1; ?????? delay(1);//调试的时候,由于我不能确定P0是否被赋值为temp,这里可以添加一句//temp=0xfd,再调试中下面的语句csda=1加断点,看看P0是否等于temp,如果是说明AD //转换器的输出值temp确实被DA转换器读入,并将此值送给P0来控制DA转换器的发光//二极管 ?????? P0=temp; ?????? csda=1; ?????? delay(10); } void main() { ?????? init(); ?????? while(1) ?????? { ????????????? start(); ????????????? delay(10); ????????????? P1=0xff; ????????????? P0=0; ????????????? adrd=0; ????????????? temp=P1; ????????????? adrd=1; ????????????? P0=0xff; ????????????? delay(20); ????????????? P1=temp;//发光二极管亮,可以判断AD转换器是否起作用 ????????????? admode();????????????? ?????? } } |
|
嵌入式 最新文章 |
基于高精度单片机开发红外测温仪方案 |
89C51单片机与DAC0832 |
基于51单片机宠物自动投料喂食器控制系统仿 |
《痞子衡嵌入式半月刊》 第 68 期 |
多思计组实验实验七 简单模型机实验 |
CSC7720 |
启明智显分享| ESP32学习笔记参考--PWM(脉冲 |
STM32初探 |
STM32 总结 |
【STM32】CubeMX例程四---定时器中断(附工 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 6:45:26- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |