文章目录

  • 前言
  • 一、功能要求
    • 1、功能图
  • 二、硬件分析
    • 1、功能一硬件电路:
    • 2、功能二硬件电路:
    • 3、功能三硬件电路:
    • 4、功能四硬件电路:
  • 三、代码
    • 1、整体流程(主函数)
    • 2、138选择函数与关闭蜂鸣器与串口
    • 3、检测,初始化定时器0,串口
    • 4、中断下的数码管刷新显示
    • 5、按键、串口控制LED
      • ①、规定串口控制协议
      • ②、串口控制
      • ③、按键控制
    • 6、控制整合(源码)
  • BUG总结

前言

本人是某大学一普通大一学生,磨磨唧唧学了一学期51,但没有实践过。听学长学姐推荐蓝桥杯比赛,就报名学习蓝桥杯比赛开发板。于是就有了我想写博客记录学习经历。第一篇博客,写的菜随便骂(不是


一、功能要求

1、功能图

二、硬件分析

众所周知,CT107D开发板的基础元器件由74HC138(后面简称138)和73HC573(后面简称573)扩展IO来控制。

如图:YNC接在对应573的LE引脚。

即为138通过四个或非门(74HC02)来控制不同的锁存器,进而控制不同的基础元器件。因此,可写一个选择573的函数,方便进行调用。

1、功能一硬件电路:



如图可知,当138选中Y5C时P0口控制步进电机,继电器,蜂鸣器。只需控制N_BUZZ,N_RELAY输出高电平即可关闭蜂鸣器和继电器,完成功能一·。(ULN2003左IN输入电平与右OUT输入电平相反)

2、功能二硬件电路:


138选中Y4C,写一个函数实现流水灯效果。(这大概是大家最熟练的 /狗头)

3、功能三硬件电路:


CT107D板子为共阳数码管,因此Y6C控制阳极(哪个数码管显示),Y7C控制阴极(数码管显示扫描数字)。因为要节约IO口,数码管显示就要用到我们最爱的动态扫描了。

动态扫描:一次点亮一个数码管,并显示相应的数字,即可做到16个io口控制八个数码管,因为用上了138和573,实际上只用了8+3个IO口(P0口可以复用)。

4、功能四硬件电路:


LED电路在上面

CON3跳线帽接到23脚上!!(此处只控制两个灯,暂用不到动态扫描)

三、代码

1、整体流程(主函数)

Created with Raphaël 2.2.0开始关闭蜂鸣器、继电器初始化检测初始化串口、定时器0刷新数码管数据扫描按键扫描串口数据while(1)yes

设定定时器中断,计算时间的同时动态刷新数码管(中断刷新数码管可以防止止数码管出现不显示的情况)

void main()
{Close_Other();  //关闭蜂鸣器与继电器Init_Test();    //初始化检测函数Init_UART();   //初始化串口Init_Timer0();  //初始化定时器0中断,每1ms进入一次中断   while(1){SMG_Show();//每隔200ms刷新显示一次数码管KeyState();  //扫描按键状态,内部执行按键函数UARTState(); //扫描串口状态,内部执行串口函数}
}

2、138选择函数与关闭蜂鸣器与串口

void Sel_HC138(unsigned char n)
{/*通过控制P2口控制138,此算法可不影响P2口后三位状态
*/switch(n){case 4:P2 = (P2 & 0x1F) | 0x80;break;//LEDcase 5:P2 = (P2 & 0x1F) | 0xa0;break;//步进电机、蜂鸣器、继电器case 6:P2 = (P2 & 0x1F) | 0xc0;break;//SMG阴极case 7:P2 = (P2 & 0x1F) | 0xe0;break;//SMG阳极case 0:P2 = (P2 & 0x1F) | 0x00;break;//锁存数据,退出前一锁存器,防止改变数据。default: break;}
}void Close_Other()
{Sel_HC138(5);  //选择Y5锁存器P0 = 0x00;     //关闭所有设备Sel_HC138(0);  //锁存数据,退出状态
}

位运算解析

位运算符 1 0
& x本身 0
I 1 x本身
^ x相反 x本身

"x"为对应计算数,如: 0bxxxx & 0b1111 = 0b1111;

3、检测,初始化定时器0,串口

检测函数,LED流水灯与数码管流水灯的实现。

/*流水灯应该不用说什么吧*/
void SMG_Test()
{unsigned char i;for(i=0;i<9;i++){Sel_HC138(6);P0 = 0x80>>i;Sel_HC138(7);P0 = 0x00;  //数码管流水灯Delay(60000);Delay(60000);Delay(60000);}
}void Init_Test()
{unsigned char i;Sel_HC138(4);for(i=0;i<8;i++){P0 = ~(0x80>>i);Delay(60000);Delay(60000);Delay(60000);}P0 = 0xFF;//流水灯结束Sel_HC138(0);SMG_Test();
}

初始化串口和定时器0寄存器,可用STC烧录软件快速完成。

void Init_UART()
{TMOD = TMOD | 0x20; //定时器1八位重装载模式TH1 = 0xfd;         //波特率9600TL1 = 0xfd;TR1 = 1;SCON = 0x50;        //串口模式AUXR = 0x00;ES = 1;             //打开串口中断EA = 1;
}void Init_Timer0()
{TMOD |= 0x01;   //定时器零十六位计数模式TH0 = (65535 - 1000)/256;TL0 = (65535 - 1000)%256;//设定1ms延时TR0 = 1;ET0 = 1;EA = 1;
}

reg52.h中没有定义AUXR寄存器,因此需要自行定义sfr AUXR = 0x8e(0x8e为AUXR地址)或者使用stc15f2k60s2.h头文件。

4、中断下的数码管刷新显示

①、初始化所需全局变量

//初始化
unsigned char t_h=0,t_m=0,t_s=0;//时,分,秒(定时器计数)
unsigned char code SMG_num[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90
};//共阳数码管数字数组
unsigned char SMG_COM[8] = {0,0,0,0,0,0,0,0
};//数码管显示内容,将每位所得数字对应的SMG_num值存入该数组中

②、利用中断计算t_h, t_m, t_s(时,分,秒)

因为前面中断设置每1ms进入一次,所以可设置静态变量Num1ms利用中断进入次数计算时间。计算如下:

 static unsigned int Num1ms = 0;Num1ms++;//进入一次1ms数加一if(Num1ms >= 1000)  //1000ms == 1s{Num1ms = 0;  //1s时Num1ms归零重新开始计算t_s++;if(t_s >= 60)  //秒分计数60进1{t_s = 0; //进1归零t_m++;if(t_m >= 60) //分时计数60进1{t_h++;t_m = 0; //进1归零}}}

③、得出时间,对时间处理并存入SMG_COM[ ]数组中

将所得的每个数字用SMG_num的形式表达并存入对应SMG_COM(数码管数据备份)中。

void SMG_Show()
{SMG_COM[7] = SMG_num[t_h/10];SMG_COM[6] = SMG_num[t_h%10];SMG_COM[5] = 0xBF;SMG_COM[4] = SMG_num[t_m/10];SMG_COM[3] = SMG_num[t_m%10];SMG_COM[2] = 0xBF;SMG_COM[1] = SMG_num[t_s/10];SMG_COM[0] = SMG_num[t_s%10];//下方为串口数据处理/*TimerChar[0] = t_h/10+'0';TimerChar[1] = t_h%10+'0';TimerChar[2] = '-';TimerChar[3] = t_m/10+'0';TimerChar[4] = t_m%10+'0';TimerChar[5] = '-';TimerChar[6] = t_s/10+'0';TimerChar[7] = t_s%10+'0';TimerChar[8] = '\r';TimerChar[9] = '\n';*/
}

④、完善中断

我们已经对数码管写出了三个函数,不过还差一个最重要的函数!即:显示函数

因为要设置每个数码管间的刷新间隔为1ms,所以设置控制某个数码管是否显示时应再中断中设置。

void it0() interrupt 1
{static unsigned int Num1ms = 0;TH0 = (65535 - 1000)/256;TL0 = (65535 - 1000)%256;Num1ms++;if(Num1ms >= 1000){Num1ms = 0;t_s++;if(t_s >= 60){t_s = 0;t_m++;if(t_m >= 60){t_h++;t_m = 0;}}}SMG_Scan(Num1ms%8);//Num1ms%8所得为,进入中断时,应当亮的数码管号
}

P0控制数码管的显示内容,对应SMG_num[ ]中的值。
例如:P0 = SMG_num[0]且该数码管阳极为正时,对应数码管显示为0。
完善SMG_scan为

void SMG_Scan(unsigned char i)
{Sel_HC138(6);//打开数码管阳极锁存器P0 = 0x80>>i;//选择对应数码管使其发光Sel_HC138(7);//选择数码管阴极锁存器P0 = SMG_COM[i];//输出对应i的值Sel_HC138(0);//锁存数据,退出锁存器
}

5、按键、串口控制LED

①、规定串口控制协议


高四位选择功能,当高四位值为A时,第四位控制灯光开关。

②、串口控制

接收数据存入Char_RI中

void UARTIT1() interrupt 4
{if(RI)             //当检测到接收数据{RI = 0;         // RI清零,防止不停接收Char_RI = SBUF; //接收数据存入Char_RI中}
}

处理Char_RI并实现规定的串口控制协议,处理完数据注意需要清空Char_RI的值,防止不停发送指令!!!

void SendTimer0(unsigned char *str)//接收时间字符串
{while(*str!='\0')   //当检测到'\0'退出{SBUF = *str++;  //发送一位字节字符串while(TI == 0); //当发送完毕TI = 0;         //TI置零}Char_RI = 0;     //清空Char_RI的值防止不停发送!
}void UARTState()
{if(Char_RI == 0xb0)  //开头为b发送当前时间{SendTimer0(TimerChar); //发送当前时间}else if((Char_RI>>4)==0x0a)开头为a控制前四位LED{P0 = LED_data; //读取LED锁存器数据Sel_HC138(4);  //选择LED锁存LED_data = (P0 | 0x0f)&(~(Char_RI&0x0f)); //改变LED_data中信息P0 = LED_data; //储存数据Sel_HC138(0);  //锁存数据Char_RI = 0;   //停止接收信息}
}

看到这里,很多同学可能会对时间字符串怎么来的有问题。由于中断中应尽量少写程序,防止中断时间误差增大,所以我们对t_h,t_m,t_s处理成字符串形式的代码与数码管数据处理一同放在SMG_show中。当然,如果觉得这样不够整齐也可以另开一个函数放在主函数中,这里我就偷一下懒吧。(见4-③,自行去掉下划线)

③、按键控制

众所周知,按键按下与弹起会有抖动问题,惹人很烦

抖动问题的软件解决有两种方法,一种是延迟10ms左右消抖,另一种是诸位读取字节(需要中断)。我们暂且用延迟法,而延迟时我们可以在while函数中写上时间处理的函数,又因为数码管刷新是中断函数,所以按键可以不影响到数码管的显示~~(几乎不影响)~~

void KeyState()
{if(Key5 == 0){Delay(500);//延迟if(Key5 == 0){while(Key5 == 0){SMG_Show();}P0 = LED_data;Sel_HC138(4);LED_data = (LED_data&0xbf)|((LED_data&0x40)^0x40);P0 = LED_data;Sel_HC138(0);}}if(Key4 == 0){Delay(500);if(Key4 == 0){while(Key4 == 0){SMG_Show();}P0 = LED_data;Sel_HC138(4);LED_data = (LED_data&0x7f)|((LED_data&0x80)^0x80);P0 = LED_data;Sel_HC138(0);}}
}

6、控制整合(源码)

因为只有一个P0口,而在锁存器切换过程中P0口的无法及时改变可能导致鬼影、led控制出错等问题,所以我们设置两个数据来存储对应锁存器数据,一个是LED_data,另一个SMG_data,在切换寄存器时,我们可以先变换对应的data,再把XXX_data赋值给P0,这样就可以避免一些P0变更不及时或者突变的错误。

源码度娘:
链接:https://pan.baidu.com/s/1poUThLg9ckJN2FCiFsTZsg
提取码:ci16


BUG总结

1、不能不设置存储锁存器数据,并且在切换锁存器,控制P0时,应该先改变对应存储锁存器的数据。
2、延时消抖需要在延时中写入需要功能防止按下按键时其它功能不反应。
3、串口接收的数据处理完后清零,防止不停接收!
4、位运算时,若想将某一或几位赋1或0应先将该(几)位统一清零或置一。

蓝桥杯学习笔记--工厂灯光控制系统(小蜜蜂笔记作业)相关推荐

  1. 【蓝桥杯单片机】工厂灯光控制系统案例解析(小蜜蜂老师基础综合实训)

    工厂灯光控制系统案例解析 题目 流程图 关键点复盘 参考代码(IO模式) 题目 流程图 关键点复盘 设备检测--移位 L1~L8在板子上是从左至右,但是在对P0口赋值时是16进制从高位(L8)-> ...

  2. 【蓝桥杯08】——工厂灯光控制系统

    设计程序,用于本地和远程控制现场灯光的开关,并能通过串口远程读取工厂的系统运行时间. 设计系统初始化函数,关闭蜂鸣器和继电器等无关设备. 设计设备检测函数,首先检测LED指示灯,从L1~L8依次逐个点 ...

  3. 蓝桥杯单片机CT107D_13_工厂灯光控制系统

    需求:(题目来自小蜜蜂老师) #include<reg52.h> sfr AUXR = 0x8e; //设置辅助寄存器AUXR sbit S7 = P3^0; //独立按键S7 sbit ...

  4. 【蓝桥杯学习笔记】9. 解立方根——二分法+牛顿迭代法

    系列文章目录 [蓝桥杯学习笔记]1. 入门基本语法及练习题 [蓝桥杯学习笔记]2. 常用模型----最大公约数和最小公倍数 [蓝桥杯学习笔记]3. 质数判断 [蓝桥杯学习笔记]5. 矩阵乘法 [蓝桥杯 ...

  5. 蓝桥杯学习笔记三:Delay函数毫秒变微秒

    平时的HAL_Delay()都是毫秒单位的,但是进去这个函数看看的话,也看不出来是咋回事,我也不理解.但是就说在网上知道了一个方法:用SysTick_Config();这个函数就是来控制Delay函数 ...

  6. 2017年第八届蓝桥杯JavaB组省赛 刷题笔记、思路及答案

    前言 本人是二本院校大二的计算机系学生,已经报名了下一届的蓝桥杯省赛,整个寒假在家(这次的寒假挺久的哈哈)在b站学习了一些算法(现在会bfs走迷宫.dfs相关算法.递归回溯.常见排列算法),但是还是有 ...

  7. 蓝桥杯学习记录-基础练习

    注:每天都更新哦~,题目下面的代码都是经过测试正确的,欢迎有更好算法的大神指正,我会把您的代码也附上,相互学习. 蓝桥杯-基础练习:所有题 十六进制转八进制 进制转换 字符 循环 十六进制转十进制 进 ...

  8. 2022蓝桥杯学习——6.双指针、BFS和图论

    一.双指针 关于双指针 核心思想就是优化!! 双指针只用一层循环,虽然里面是while,但j只执行了n次,所以ij一共就是2n,时间复杂度就是O(n) , 这种题一般先写出暴力算法,然后看单调性,如果 ...

  9. 2023蓝桥杯学习与刷题建议

    前两天天给你们组了队,经过两天发现各位都有这样的问题: 不愿意交流. 小组不会规划刷题计划. 可能是因为没有人带头和具体刷题计划,所以都处于迷茫,不交流.不刷题. 还有可能是大家都不认识,都比较羞涩. ...

最新文章

  1. 拉普拉斯平滑处理 Laplace Smoothing
  2. 51nod 1402最大值
  3. 在Tomcat中部署seam工程
  4. java快捷键禁用_pycharm 掌握这些快捷键,你就是大神!!
  5. php xml 实例教程,php解析xml方法实例详解,解析xml实例详解_PHP教程
  6. mysqloffset什么意思_mysql查询时offset过大影响性能的原因和优化详解
  7. ubuntu环境下载android源码
  8. matlab带未知数的劳斯判据,自动控制原理实验用Matlab软件编制劳斯判据程序并解题(《学习辅导》例4.3.5)...
  9. 6个超炫酷的HTML5电子书翻页动画
  10. 1、git提交码云拉取创库地址
  11. c语言让数码管显示时间,请问51单片机肿么编写程序让8个数码管显示时间(时分秒)...
  12. 在线小游戏编程工具使用教程
  13. Markdown教程常用语法随笔
  14. 生日快乐程序_时光匆匆,爱你不变——祝星广十七岁生日快乐
  15. 小X与神牛(dfs)
  16. 有道笔记链接地址 -----关于python
  17. S - 歌德巴赫猜想
  18. 如何有效的制定团队能力提升计划?
  19. 使用本地CentOS-7-x86_64-Vagrant-2004_01.VirtualBox.box创建三个k8s集群虚拟机
  20. 18-pytest-配置文件pytest.ini使用

热门文章

  1. 互联网大厂面试笔试题大全
  2. 2019上半年总结和下半年的目标
  3. 物料管理系统最基本的功能有哪些?
  4. 笔记整理5----Java语言高级(五--完结)21 字符流与字节流+22 多线程+23 网络编程
  5. 随机森林算法Matlab实现
  6. 百度人工智能发展怎么样啦?开发者能做什么?
  7. 8 行代码用Python画一个中国地图 !
  8. OA系统:企业驰骋信息化道路的神器
  9. python网络抓包工具_抓包工具 Charles 用法详解
  10. R语言入门(学习笔记)