零基础蓝桥杯单片机学习_第四章_数码管显示
看到板子上一大块暗着的像时钟一样的数码管吗今天让我们给他点起。一、原理图讲解如图是数码管模块的原理图可以看到最下面的数码管有左右两边端口。随便挑一个不难发现左边的控制一个’8’中哪一横亮(A’-a)右边则控制哪个’8’亮(COM1-DP1)。那么就有问题了数码管一次只能亮一个’8’怎么做到同时显示数字只要让每个’8’以极短的时间显示就行。想要显示数码管这就是关键每2ms切换一根数码管显示。二、要求提出每2ms切换数码管显示数码管的显示不能干扰正常循环代码否则可能导致阻塞。三、代码编写前情提要这块数码管是共阳极即低电平点亮。CACommon Anode 阳极共同连接阴极相互独立。与之相反的是CCCommon Cathode1.让我们先用while函数点亮一根数码管。比如先点亮原理图左边数码管的左边第二个‘8’的bc,使其显示“1”(COM2-c)基本思路1.将P0改为指向COM2P0 0000 0010_74HC138函数选中Y62.将P0改为指向bc即0000 01100xF9_74HC138函数选中Y7于是就有了下面代码待填充2.数组存储每次都写0xF9等十六进制太麻烦了这里我们引入数组做到输入一个数就能代替一个十六进制。数组的语法如下需要注意的是在大多数的编程语言0是作为数组的开端的。所以如果我希望取0xF8尽管它在第8个但我得取数组的第七位。当我需要取数组内数时只需写nixie_table[n]即可n是0-9的正整数。当需要修改数组内数字时只需写nixie_table[n]x即可n是0-9的正整数x是任意0-255的数在任何进制下x范围随定义的数组输出数字类型决定广告不想一个个推打开“SEG_TABLE_对应断码.pdf”文件找到你的专属十六进制断码笑PS部分考纲要求的显示还是要自己推的但减了不少麻烦。3.定时器想要2ms运行一次代码还不阻塞main循环我们就需要引入一个定时器。如果我们初始化一段2ms的定时器并为定时器赋予一串代码软件就会这样跑黑为main红为定时器。实际上红段会小很多此处仅是为了理解。可以看到即使只有一个核心单片机也会在规定时间运行要执行的代码并且不阻塞源代码的持续。在ISC中我们可以直接生成定时器代码具体步骤如下。在软件界面打开“定时器计算器”调整以下参数1.时钟频率12.0000Hz考纲要求2.定时长度1毫秒便于计量计算3.选中“使能定时器中断”点击生成C代码并复制你会得到这串代码相关注释已经放在旁边void Timer0_Isr(void) interrupt 1 { //这里就是红线部分 } void Timer0_Init(void) //1毫秒12.000MHz { AUXR | 0x80; //定时器时钟1T模式 TMOD 0xF0; //设置定时器模式 TL0 0x20; //设置定时初始值 TH0 0xD1; //设置定时初始值 TF0 0; //清除TF0标志 TR0 1; //定时器0开始计时 ET0 1; //使能定时器0中断EA 1; //使计时器开启这段要自己写否则开不了 }将它直接放到main.c里面于是就有//main.c #include STC15F2K60S2.H #include _74HC138.h #include Led.h void Timer0_Init(void) //计时器 { AUXR | 0x80; TMOD 0xF0; TL0 0x20; TH0 0xD1; TF0 0; TR0 1; ET0 1; EA 1; } void Timer0_Isr(void) interrupt 1 { //红线部分 } void main() { //刚上电的运行 while(1) { //初始化后的总循环蓝线部分 } }好定时器到这里就结束了后面我们将用计时器直接使灯循环亮起。4.开始编写请读者建立一个意识数码管的循环显示与更改需要解耦占据更小的运行时间同时还使代码更易编写。没看懂上面的话翻译一下就是我们可以将用数组保存数码管需要显示的数字并创建一个全新的使数码管按照数组点亮的函数循环2ms运行。如图右边扫描函数一直运行一直使数码管亮起左边while函数只需修改数组。如此我们就需要创建三个函数让单个数码管‘8’亮起的函数让数码管一直循环亮的扫描函数与修改数组的函数。//nixie,c // #include STC15F2K60S2.H #include _74HC138.h #include nixie.hcode1unsigned char nixie_table[11] {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0xFF}; //0 1 2 3 4 5 6 7 8 9 Null unsigned char nixie_display[9] {10,10,10,10,10,10,10,10,10}; //让单个数码管‘8’亮起的函数 void nixie(unsigned char Location, display) // { P0 0xFF; //对P0改为0xFF为所有数码管置零做准备避免不必要的显示 _74HC138_init(7); //选中Y7更改数码管显示为全暗 P0 0x01 (Location-1); //使用P0预选中相对应8为点亮做准备 _74HC138_init(6); //选中Y6结合P0选中相对应的8 P0 display; //指明对应数码管的显示 _74HC138_init(7); //选中Y7更改数码管的显示 } //让数码管一直循环亮的扫描函数 void nixie_loop() {static2unsigned char n 1; //声明一个char作为每次刷新的位置记录 nixie(n,nixie_table[nixie_display[n]]); //每次char刷新后执行一个8的点亮 n; //每次数码管点亮后自动将位置后移一格 if(n 9){n 1;} //当n超过8了自动回到1 } //修改数组的函数 void set_nixie_display(unsigned char Location, display){ nixie_display[Location] display; //将显示数组调整成需要的数 }那么这个时候就可以使用定时器让数码管点亮了此处我直接把代码贴出来并做出注释。//main.c #include STC15F2K60S2.H #include _74HC138.h #include nixie.h void Timer0_Init(void) { AUXR 0x7F; TMOD 0xF0; TL0 0x18; TH0 0xFC; TF0 0; TR0 1; ET0 1; EA 1; //这一段别忘了加 } void Timer0_Isr(void) interrupt 1 { static unsigned char count1 0; //从软件开始的一刻设定一个1ms自动加1的数方便计时。 count1; if(count1 2) //如果2ms了 { nixie_loop(); //执行一次循环让所有8亮一下 count1 0; //置零到了下一次2ms可以循环 } } void main() { _74HC138_init_all(); //初始化所有74HC138下的硬件 Timer0_Init(); //初始化并开启定时器 while(1) //软件主循环 { set_nixie_display(1,2); //设置第一个灯管亮“2”这个数字 } }此处省略关于头文件的书写与74HC138选中的函数有需要可以查看上一章节也可以直接下载文档并导入。文档链接https://hkpanel.sakurarun.vip/s/G5zirAY7sBE5E?operateNodelocal那么到现在我们就完成了数码管灯的点亮是时候留点思考题了在所有灯电源灯除外熄灭的前提下编写一个20s的计时器当最后3s时LED灯4号亮起0s后一直保持0s不要求数字在哪里显示【可能用到的计算{/除得商12/101}{%除得余12%102}】//main.c #include STC15F2K60S2.H #include _74HC138.h #include nixie.h #include LED.hvoid Timer0_Init(void){AUXR 0x7F;TMOD 0xF0;TL0 0x18;TH0 0xFC;TF0 0;TR0 1;ET0 1;EA 1; //这里记得补充。}static char time 21;//此处使用21因为count2运行时先减1再显示void Timer0_Isr(void) interrupt 1{static unsigned char count1 0;static unsigned int count2 0;//设置一个count2方便以秒计时count1;count2;if(count1 2){nixie_loop();count1 0;}if(count2 1000){ //如果1s之后if(time0){ //且20s倒计时还没到0stime–; //先减1sset_nixie_display(1,time/10); //再将十位调到时间与10整除得到的商set_nixie_display(2,time%10); //再将个位跳到时间与10整除得到的余if(time3) //如果时间小于或等于3s{LED(4);} //把4号LED亮起来count2 0;} //并置零count2等待下一个1s}}void main(){_74HC138_init_all();Timer0_Init(); //这里记得初始化函数不要让定时器开不了。while(1){}}