第十课、虚拟LED和数码管
课程主要内容:
本次课程专注于教授如何利用虚拟软件进行实验和调试,特别针对没有实验箱或最小系统版的学员。讲师首先介绍了虚拟软件的强大功能,包括虚拟显示、键盘以及多种调试工具,并强调了软件(最新ISP软件)与硬件(擎天柱)的准备。课程内容涵盖使用虚拟软件控制LED显示,通过定义变量来操作P2端口的流水灯和P10端口的闪烁灯,以及控制虚拟数码管显示字符串、整数和浮点数。此外,还讲解了如何通过虚拟键盘接收按键输入并控制数码管显示输入的数字。并鼓励学生课后练习密码锁项目,以深化对虚拟调试与实验的理解。
学习感悟:
LED40_SendData()为所有管脚;LED40_SetPort()为修改单独一组管脚;LED40_SetBit()为单独一个管脚;LED_ClrBit()设置单独一个管脚为零(清零);LED_SetBit()设置单独一个输出高电平(置一)。在ISP中的“调试仿真接口”下的“接口协议及帮助”中也有详细介绍。命令头中的“4C 45 44 28”实际上就是ASCII码中的“LED(”。stc32_stc8_usb.h在新的版本中已经修改为Ai8051.h,相应的调用都要修改。在第二个例子中KEY1_COUNT必须申明为u32(long)类型,否则在程序运行的过程中只要大于6次就会显示乱码。根据程序分析因为要将其乘以10000,这时因为u16(int)类型最大是65535,所以产生了溢出。也根据这一情况来开,在进行运算时,如果你声明一个类型,它的运算结果并不会直接放到被赋值的空间中去,而是暂时存在一个与你当前数据类型相同的一个临时空间中,如果空间不够就会产生溢出。在使用软件仿真的数码管编程时发现其不支持显示超过F字符的字符(OPEN只能显示E字符),只好又利用实验箱中的数码管进行程序的编写。效果和程序完全是两码事,感觉有机会大家最好还是要在硬件上编写测试为好。
课后小练:
密码锁
1.没有输入时,显示“--------“
2.有输入时,按下一个按键,开始按顺序写入
例如,第一个按下 1,显示“1-------”
例如,第二个按下 3,“显示“13------“
3.当按下的密码为“12345678”时,数码管显示 open 的字符,否则(输入8位错误的),还是显示“--------“。
main.c
- #include <config.h>
- #include "task.h"
-
- char *USER_DEVICEDESC = NULL;
- char *USER_PRODUCTDESC = NULL;
- char *USER_STCISPCMD = "@STCISP#";
-
- extern bit receiveData; //跨文件(io.c)调用
- extern u32 REC_NUM; //跨文件(io.c)调用
-
- void main()
- {
- Sys_init(); //系统初始化
- usb_init(); //USB口初始化配置
-
- IE2 |= 0x80; //EUSB位置位,打开USB
- EA = 1; //总中断置位,打开中断
-
- Timer0_Init(); //开始1ms延时
-
- while(DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
-
- while(1)
- {
-
- if (bUsbOutReady) //如果接收到了数据
- {
- if(UsbOutBuffer[5] >= '0' && UsbOutBuffer[5] <= '9')
- {
- REC_NUM = UsbOutBuffer[5] - '0'; //接收串口键盘的数据,将ASCII码的字符变换为数值赋值
- receiveData = 1; //有效接收
- }
- else
- {
- receiveData = 0; //无效接收
- }
-
- usb_OUT_done(); //清除当前接收区
- }
-
- Task_Pro_Handler_Callback(); //如果Run的状态为1(真),就执行函数
-
- }
- }
-
- void Timer0_Isr(void) interrupt 1 //1ms执行一次
- {
- Task_Marks_Handler_Callback(); //计数位进行递减到0时将Run的状态置1,在这里就是1ms减1
- }
复制代码
io.c
- #include "io.h"
- bit receiveData = 0; //是否接收新字符,0为未接收,1为已接收;main.c中调用此参数
- bit openTag = 0; //开锁状态,0为关,1为开
- u32 keyCount = 0; //按键计数
- u32 REC_NUM; //接收的字符;main.c中调用此参数
-
- u8 SEG_NUM[]= //段码字库
- {
- 0x3F, /*'0', 0*/
- 0x06, /*'1', 1*/
- 0x5B, /*'2', 2*/
- 0x4F, /*'3', 3*/
- 0x66, /*'4', 4*/
- 0x6D, /*'5', 5*/
- 0x7D, /*'6', 6*/
- 0x07, /*'7', 7*/
- 0x7F, /*'8', 8*/
- 0x6F, /*'9', 9*/
- 0x79, /*'E', 10*/
- 0x54, /*'N', 11*/
- 0x5C, /*'O', 12*/
- 0x73, /*'P', 13*/
- 0x40, /*'-', 14*/
- 0x00, /*' ', 15*/
-
- };
-
- u8 T_NUM[]= //位码,使用时要取反
- {
- 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
- };
-
- //填充初始值为“--------”,此为段码显示
- u8 fmt[8] = {0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40};
-
- //填充初始值为“12345678”,修改此处即可修改开锁密码,此为段码显示
- u8 passwordValue[8] = {0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F};
-
- void Init_595(void)
- {
- HC595_SER = 0;
- HC595_RCK = 0;
- HC595_SCK = 0;
- }
-
- void Send_595(u8 dat)
- {
- u8 i;
-
- for(i = 0;i < 8;i++)
- {
- dat <<= 1; //溢出位到CY
- HC595_SER = CY; //数据输入
- HC595_SCK = 1; //产生上升沿
- HC595_SCK = 0; //复位
- }
- }
-
- void Display_Seg(u8 HC595_1,u8 HC595_2)
- {
- Send_595(HC595_1); //段码输出,低电平点亮
- Send_595(HC595_2); //位码输出,低电平点亮
-
- HC595_RCK = 1; //数据输出
- HC595_RCK = 0; //复位
- }
-
- bit areArraysEqual(unsigned char arr1[],unsigned char arr2[]) { //比较数组是否相等,不等返回0,相等返回1
- u8 tempVol1;
- for (tempVol1 = 0; tempVol1 < 8; tempVol1++) {
- if (arr1[tempVol1] != arr2[tempVol1]) {
- return 0;
- }
- }
- return 1;
- }
-
- void KEY_Task(void)
- {
- u8 i;
-
- if(receiveData == 1 && openTag == 0) //比较是否接收到新字符,并且开锁状态为关
- {
-
- fmt[keyCount] = SEG_NUM[REC_NUM];
-
- keyCount++;
-
- if(keyCount == 8)
- {
- keyCount = 0;
-
- if(areArraysEqual(fmt,passwordValue))
- {
- openTag = 1;
-
- fmt[0] = SEG_NUM[14]; //显示"-"
- fmt[1] = SEG_NUM[14]; //显示"-"
- fmt[2] = SEG_NUM[12]; //显示"O"
- fmt[3] = SEG_NUM[13]; //显示"P"
- fmt[4] = SEG_NUM[10]; //显示"E"
- fmt[5] = SEG_NUM[11]; //显示"N"
- fmt[6] = SEG_NUM[14]; //显示"-"
- fmt[7] = SEG_NUM[14]; //显示"-"
- }
- else
- {
- for(i = 0;i < 8;i++)
- fmt[i] = SEG_NUM[14]; //全部显示"-"
- }
- }
- receiveData = 0;
- }
- else
- receiveData = 0;
- }
-
- //任务:虚拟键盘上按下数字按键在数码管显示出来
-
- void TASK_Display(void)
- {
- u8 j;
- for(j = 0;j < 8;j++)
- Display_Seg(fmt[j],~T_NUM[j]);
-
- }
复制代码
|