单片机时钟和闹钟设置,串口通信
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
CMS80F251xEVB使用
文章目录
- 前言
- 一、LCD默认进入时钟模式,P50按键按下一次进入闹钟模式,再按一次退出闹钟模式
- 二、P20按两次,选中分钟,再按一次,分钟加一,再按两次,选中秒钟,按一次,秒钟加一
- 三、时钟等于闹钟,D2灯亮灭三次,这时P20按一次,闹钟清零
- 四、P50按两次,进入串口模式
- 总结
前言
EVB板c51程序
一、LCD默认进入时钟模式,P50按键按下一次进入闹钟模式,再按一次退出闹钟模式
二、P20按两次,选中分钟,再按一次,分钟加一,再按两次,选中秒钟,按一次,秒钟加一
三、时钟等于闹钟,D2灯亮灭三次,这时P20按一次,闹钟清零
四、P50按两次,进入串口模式
代码如下:
#include "dis_timer.h"
#define KEY1_STATE_0 0
#define KEY1_STATE_1 1
#define KEY1_STATE_2 2
#define KEY1_STATE_3 3#define KEY2_STATE_0 0
#define KEY2_STATE_1 1
#define KEY2_STATE_2 2
#define KEY2_STATE_3 3#define SINGLE_KEY1_TIME 1 //10ms
#define KEY1_INTERVAL 30 //300ms#define SINGLE_KEY2_TIME 1
#define KEY2_INTERVAL 30#define KEY1_NONE 0 //
#define KEY1_SHORT 1 //单击
#define KEY1_DOUBLE 2 //双击#define KEY2_NONE 0
#define KEY2_SHORT 1
#define KEY2_DOUBLE 2
unsigned char leddata[16][2]={{0x07,0x0d},{0x00,0x05},{0x05,0x0b},{0x01,0x0f},{0x02,0x07},{0x03,0x0e},{0x07,0x0e},{0x01,0x05},{0x07,0x0f},{0x03,0x0f},{0x07,0x07},{0x06,0x0e},{0x07,0x08},{0x04,0x0f},{0x07,0x0a},{0x07,0x02}};
unsigned char leddata1[10][2]={{0x0f,0x0d},{0x08,0x05},{0x0d,0x0b},{0x09,0x0f},{0x0a,0x07},{0x0b,0x0e},{0x0a,0x0e},{0x09,0x05},{0x0a,0x0f},{0x0b,0x0f}};
unsigned char dat[4]={0x89,0xAB,0xCD,0xEF};
int flag=0,flag1=0,flag2=0,flag3=0,flag4=0,flag5=0,flag6=0,min_sec;
unsigned char P20_KeyValue,P20_KeyValue1,P50_KeyValue;
unsigned char P20_flag_10ms_key,P20_flag_10ms_key1,P50_flag_10ms_key;
unsigned int s1,s2,s3,s4,ss3=0,ss4=0,ss1=0,ss2=0;
unsigned int we,i,time=0,time1,time2,t1,t2,t3,temp,temp1,temp2;//***************************************************//
//************Config************//
//***************************************************//
void UART0_Config(void)
{ BRTCON=0X80; //BRT使能;BRTDL=0x64;//计数器初值,65380,波特率9600;BRTDH=0xff; FUNCCR=0x05; //UART0,BRT溢出时钟SCON0=0X70; //多机控制,接受使能,8位异步模式PCON=0X80;//波特率加倍PS_RXD0=0X25;//P25作为引脚RXP25CFG=0X02;//P25 RX功能P24CFG=0X02;//P24 TXD0功能ES0=1;//允许中断
// uint16_t BRTValue = 0;
// uint32_t BaudRateVlue = 9600;
//
//
// // (1)设置UARTx的运行模式
//
// UART_ConfigRunMode(UART0,UART_MOD_ASY_8BIT, UART_BAUD_BRT);
// UART_EnableReceive(UART0);
//
// //(2)配置UARTx的波特率
//
// UART_ConfigBRTClk(BRT_CLK_DIV_1);
//
// UART_EnableDoubleFrequency(UART0); /*波特率使能倍频:SMOD =1*/
//
// #ifdef USE_FORMULA //使用公式计算定时器的加载值(需要对Systemclock赋值(main.c)),USE_FORMULA 在 选项Option->C51->Preporcessor Symbols->Define中定义
// BRTValue = UART_ConfigBaudRate(UART0, BaudRateVlue) ;
// #else
// BRTValue = 65380; //使用数据手册上推荐的加载值(BRT章节)
// #endif
//
// UART_ConfigBRTPeriod(BRTValue); /*配置重装值*/
// UART_EnableBRT(); /*使能定时器*/
//
// //(3)配置IO口// GPIO_SET_MUX_MODE(P24CFG,GPIO_P24_MUX_TXD0); /*TXD0*/
// GPIO_SET_MUX_MODE(P25CFG,GPIO_P25_MUX_RXD0); /*RXD0*/
// GPIO_SET_PS_MODE(PS_RXD0, GPIO_P25); /*RXD0输入选择P25*/
//
// // (4)设置UART中断
//
// // UART_EnableInt(UART0);
// // IRQ_SET_PRIORITY(IRQ_UART0,IRQ_PRIORITY_LOW);
}void GPIO_Config(void)
{GPIO_SET_MUX_MODE(P50CFG, GPIO_MUX_GPIO); GPIO_ENABLE_INPUT(P5TRIS, GPIO_PIN_0); GPIO_SET_MUX_MODE(P20CFG, GPIO_MUX_GPIO); GPIO_ENABLE_INPUT(P2TRIS, GPIO_PIN_0); GPIO_ENABLE_UP(P2UP, GPIO_PIN_0);GPIO_SET_MUX_MODE(P21CFG, GPIO_MUX_GPIO); GPIO_ENABLE_OUTPUT(P2TRIS,GPIO_PIN_1); GPIO_ENABLE_UP(P2UP, GPIO_PIN_1); GPIO_SET_MUX_MODE(P22CFG, GPIO_MUX_GPIO); GPIO_ENABLE_OUTPUT(P2TRIS,GPIO_PIN_2); GPIO_ENABLE_UP(P2UP, GPIO_PIN_2);
}void TMR0_Config(void)//开定时器0中断
{/*(1)设置Timer的运行模式*/TMR_ConfigRunMode(TMR0, TMR_MODE_TIMING,TMR_TIM_16BIT); /*(2)设置Timer 运行时钟*/TMR_ConfigTimerClk(TMR0, TMR_CLK_DIV_12); /*Fsys = 24Mhz,Ftimer = 2Mhz,Ttmr=0.5us*//*(3)设置Timer周期*/ TMR_ConfigTimerPeriod(TMR0, 45536/256, 45536%256); // 20000*0.5us = 10ms,递增计数/*(4)开启中断*/TMR_EnableOverflowInt(TMR0);/*(5)设置Timer中断优先级*/ IRQ_SET_PRIORITY(IRQ_TMR0,IRQ_PRIORITY_LOW);IRQ_ALL_ENABLE(); /*(6)开启Timer*/TMR_Start(TMR0);
}void LCD_Config(void)//设置lcd
{/*(1)设置LED模块运行模式*/LCD_ConfigRunMode(LCD_DISPLAY_NORMAL);LCD_ConfigCOMMode( LCD_DUTY_4); //1/4DUTYLCD_ConfigVLCD(LCD_VSEL_VLCD, 15, LCD_BIAS_3); //VDD =5V, VLcv = 3.3V , 1/3biasLCD_ConfigClk(LCD_CLK_FSYS, LCD_CLKDIV_4096);LCD_ConfigResistance(LCD_FCMODE_0, LCD_R_60K, LCD_FCCTL_8);/*(2)设置COM口*/GPIO_SET_MUX_MODE(P00CFG, GPIO_MUX_ANA); //COM0GPIO_SET_MUX_MODE(P01CFG, GPIO_MUX_ANA); //COM1 GPIO_SET_MUX_MODE(P02CFG, GPIO_MUX_ANA); //COM2GPIO_SET_MUX_MODE(P03CFG, GPIO_MUX_ANA); //COM3 LCDCOMEN = 0x0f; //使能COM0~COM3/*(3)设置SEG口*/ GPIO_SET_MUX_MODE(P04CFG, GPIO_MUX_ANA); //SEG0 -> 段码屏 SEG0GPIO_SET_MUX_MODE(P05CFG, GPIO_MUX_ANA); //SEG1 -> 段码屏 SEG1GPIO_SET_MUX_MODE(P06CFG, GPIO_MUX_ANA); //SEG2 -> 段码屏 SEG2 GPIO_SET_MUX_MODE(P07CFG, GPIO_MUX_ANA); //SEG3 -> 段码屏 SEG3GPIO_SET_MUX_MODE(P10CFG, GPIO_MUX_ANA); //SEG4 -> 段码屏 SEG4 GPIO_SET_MUX_MODE(P11CFG, GPIO_MUX_ANA); //SEG5 -> 段码屏 SEG5 GPIO_SET_MUX_MODE(P12CFG, GPIO_MUX_ANA); //SEG6 -> 段码屏 SEG6 GPIO_SET_MUX_MODE(P13CFG, GPIO_MUX_ANA); //SEG7 -> 段码屏 SEG7 LCDSEGEN0 = 0xFF; //使能SEG8~SEG15 /*(6)设置SEG口数据*/LCDSEG0 = 0x00;LCDSEG1 = 0x00; LCDSEG2 = 0x00; LCDSEG3 = 0x00;LCDSEG4 = 0x00;LCDSEG5 = 0x00;LCDSEG6 = 0x00;LCDSEG7 = 0x00;/*(7)开启LCD*/LCD_Start();
}//***************************************************//
//************timer0和串口中断函数************//
//***************************************************//
void Timer0_IRQHandler(void) interrupt TMR0_VECTOR
{ TMR_ConfigTimerPeriod(TMR0, 45536/256, 45536%256); // 20000*0.5us = 10ms,递增计数time++;//lcd显示1s递增time1++;if(time1==50){t1=1; //0.5s标志位,闹钟警报灯亮灭时间time1=0; } time2++;if(time2==300){t2=1; //3s标志位,发送数据时间time2=0; } P20_flag_10ms_key=1; // 置位 10ms 定时标志P20_flag_10ms_key1=1; // 置位 10ms 定时标志P50_flag_10ms_key=1; // 置位 10ms 定时标志for(we=0;we<4;we++){if(we == 0){ LCDSEG6 = leddata[s1][0];LCDSEG7 = leddata[s1][1];}if(we == 1){ LCDSEG4 = leddata[s2][0];LCDSEG5 = leddata[s2][1];}if(we == 2){ LCDSEG2 = leddata[s3][0]; LCDSEG3 = leddata[s3][1];}if(we == 3){ LCDSEG0 = leddata1[s4][0];LCDSEG1 = leddata1[s4][1]; } } }void UART0_IRQHandler(void) interrupt UART0_VECTOR //串口中断
{//if(UART_GetSendIntFlag(UART0))
// {
// UART_ClearSendIntFlag(UART0);
// }
// if(UART_GetReceiveIntFlag(UART0))
// {// UART_SendBuff(UART0,UART_GetBuff(UART0));
// UART_ClearReceiveIntFlag(UART0);
// }if(RI0==1){temp=SBUF0; //P21=0;RI0=0;}
}//***************************************************//
//**********向FPGA发送数据***********//
//***************************************************//
void putschar ()//发送数据
{ if(temp==0x11){P22=0;t3=1;}if(t2&&t3){SBUF0 = dat[i];i++;t2=0;if(i==4){i=0;}while (!TI0);TI0=0;}}//***************************************************//
//**************LCD显示功能***************//
//***************************************************//
void LCD_Display()//时钟显示
{ if(time==100){s1++;if(s1==10){s1=0;s2++;if(s2==6){s2=0;s3++;if(s3==10){s3=0;s4++;if(s4==6)s4=0; }}} time=0; }}void CLOCKINIT()//闹钟初始化显示
{ LCDSEG6 = leddata[ss1][0];LCDSEG7 = leddata[ss1][1]; LCDSEG4 = leddata[ss2][0];LCDSEG5 = leddata[ss2][1]; LCDSEG2 = leddata[ss3][0];LCDSEG3 = leddata[ss3][1]; LCDSEG0 = leddata1[ss4][0];LCDSEG1 = leddata1[ss4][1];} void UART()//串口显示收到的数据
{if(flag6){// putschar(6);//getschar();temp1=temp>>4;temp2=temp&0x0f;LCDSEG0 = leddata[temp1][0];LCDSEG1 = leddata[temp1][1];LCDSEG2 = leddata[temp2][0];LCDSEG3 = leddata[temp2][1];LCDSEG6 = 0;LCDSEG7 = 0; LCDSEG4 = 0;LCDSEG5 = 0; }
}//***************************************************//
//***************按键读取*******************//
//***************************************************//
unsigned char key1_driver()//P20
{static unsigned char key1_state = 0;//按键状态变量static unsigned int key_time = 0;//按键计时变量unsigned char key_return=KEY1_NONE;// 清除 返回按键值switch(key1_state){case KEY1_STATE_0:// 按键状态0:判断有无按键按下if(!P20)// 有按键按下{key_time=0; // 清零时间间隔计数key1_state=KEY1_STATE_1;// 然后进入 按键状态1}break;case KEY1_STATE_1: // 按键状态1:软件消抖(确定按键是否有效,而不是误触)。按键有效的定义:按键持续按下超过设定的消抖时间。if(!P20){key_time++; // 一次10msif(key_time>=SINGLE_KEY1_TIME) // 消抖时间{key1_state=KEY1_STATE_2;// 如果按键时间超过 消抖时间,即判定为按下的按键有效。按键有效包括两种:单击或者双击,进入按键状态2, 继续判定到底是那种有效按键}}elsekey1_state=KEY1_STATE_0; // 如果按键时间没有超过,判定为误触,按键无效,返回 按键状态0,继续等待按键break;case KEY2_STATE_2:if(P20){key_return=KEY1_SHORT;// 返回 有效键值值:单击key1_state=KEY1_STATE_0;// 返回 按键状态0,继续等待按键}break;default: // 特殊情况:key_state是其他值得情况,清零key_state。key1_state=KEY1_STATE_0;break; } return key_return;// 返回 按键值
}
unsigned char key1_read()//P20
{static unsigned char key1_state1 = 0;static unsigned int key_time1 = 0; unsigned char key_return,key_temp;key_return=KEY1_NONE;// 清零 返回按键值key_temp=key1_driver();// 读取键值switch (key1_state1){case KEY1_STATE_0:// 按键状态0:等待有效按键(通过 key_driver 返回的有效按键值)if(key_temp == KEY1_SHORT) // 如果是[单击],不马上返回单击按键值,先进入 按键状态1,判断是否有[双击]的可能{key_time1=0; // 清零计时key1_state1=KEY1_STATE_1;}else// 如果不是单击,直接返回按键值。这里的按键值可能是:[双击],[无效按键]{key_return=key_temp;}break;case KEY1_STATE_1: // 按键状态1:判定是否有[双击]if(key_temp == KEY1_SHORT){key_return=KEY1_DOUBLE; // 返回 有效按键:[双击]key1_state1=KEY1_STATE_0; // 返回 按键状态0,等待新的有效按键}else{key_time1++;// 计数 时间间隔if(key_time1>=KEY1_INTERVAL) // 超过 时间间隔{key_return=KEY1_SHORT; // 返回 有效按键:[单击]key1_state1=KEY1_STATE_0;// 返回 按键状态0,等待新的有效按键}}break; }return key_return; // 返回 按键值
}unsigned char key2_driver()//P50
{static unsigned char key2_state = 0;static unsigned int key2_time = 0;unsigned char key2_return=KEY2_NONE;switch(key2_state){case KEY2_STATE_0:if(!P50){key2_time=0;key2_state=KEY2_STATE_1;}break;case KEY2_STATE_1:if(!P50){key2_time++;if(key2_time>=SINGLE_KEY2_TIME){key2_state=KEY2_STATE_2;}}elsekey2_state=KEY2_STATE_0;break;case KEY1_STATE_2:if(P50){key2_return=KEY2_SHORT;key2_state=KEY2_STATE_0;}break; default:key2_state=KEY2_STATE_0;break; } return key2_return;
}
unsigned char key2_read()//P50
{static unsigned char key2_state1 = 0;static unsigned int key2_time1 = 0; unsigned char key2_return,key2_temp;key2_return=KEY2_NONE;key2_temp=key2_driver();switch (key2_state1){case KEY2_STATE_0:if(key2_temp == KEY2_SHORT){key2_time1=0;key2_state1=KEY2_STATE_1;}else{key2_return=key2_temp;}break;case KEY2_STATE_1:if(key2_temp == KEY2_SHORT){key2_return=KEY2_DOUBLE;key2_state1=KEY2_STATE_0;}else{key2_time1++;if(key2_time1>=KEY2_INTERVAL){key2_return=KEY2_SHORT;key2_state1=KEY2_STATE_0;}}break; }return key2_return;
}//***************************************************//
//***************功能实现*************//
//***************************************************//
void CLOCK()//P50进入闹钟模式或者串口模式
{if(P50_flag_10ms_key){P50_flag_10ms_key = 0;P50_KeyValue = key2_read();switch(P50_KeyValue){case KEY2_SHORT:flag = ~flag;min_sec=0;//进入闹钟模式的标志位if(!flag){LCD_Display();//返回时钟模式} break;case KEY2_DOUBLE:flag6=~flag6;//进入串口模式的标志位 if(!flag6){LCD_Display();//返回时钟模式}break;} }
}void clock_change()//闹钟设置时间
{if(P20_flag_10ms_key && flag){CLOCKINIT();P20_flag_10ms_key = 0;P20_KeyValue=key1_read();switch(P20_KeyValue){case KEY1_DOUBLE:min_sec++;break; case KEY1_SHORT:if(min_sec>0){flag2=1;}if(min_sec%2==0){ ss3++;if(ss3==10){ss3=0;ss4++;if(ss4==6){ss4=0;}} }if(min_sec%2==1){ ss1++;if(ss1==10){ss1=0;ss2++;if(ss2==6){ss2=0;} }} break; } }if(flag2){if(ss1==s1&&ss2==s2&&ss3==s3&&ss4==s4){flag3=1;}}
}void clock_warning() //闹钟警报
{ if(flag3)//闹钟时间等于时钟时间的标志位{ if(t1&&flag1<6){ //0.5秒亮一次或灭一次,flag1闪烁三秒六次的标志位t1=0;P21=~P21;flag1++;} clock_reset(); }
}
void clock_reset() //闹钟复位设置
{if(P20_flag_10ms_key1){P20_flag_10ms_key1 = 0;P20_KeyValue1=key1_read();switch(P20_KeyValue1){case KEY1_SHORT:flag4=1;break;} if(flag4){ss1=0;ss2=0;ss3=0;ss4=0;flag3=0;flag1=0;flag4=0;flag2=0;min_sec=0;//闹钟清零,警报标志位清零,设置闹钟的按键次数清零}}
}
void CLOCK_SET()//时钟模式进入闹钟模式或者串口模式以及返回时钟模式的函数调用
{LCD_Display();//时钟模式CLOCK();//P50单击进入闹钟显示UART();//P50双击进入串口显示clock_change();//P20设置闹钟时间clock_warning();//闹钟警报以及警报后P20按一次,各标志位清零,闹钟时间清零
}
总结
串口模式可以实现与FPGA的数据收发通信。
单片机时钟和闹钟设置,串口通信相关推荐
- 9-《电子入门趣谈》第一章_一切从单片机开始-1.3.6串口通信
好消息:请在手机淘宝或闲鱼上搜索"电子入门趣谈",有惊喜哦 :) 我把全本电子入门趣谈的电子版(包括科技提升和理论升华部分,共计50余万字)放到上面开始兜售啦,如果您真的喜欢这本书 ...
- 使用51单片机采用中断方式进行串口通信的学习记录:
使用51单片机进行串口通信的学习记录之中断方式: 1.51单片机采用中断方式的串口通信过程及程序分析: 所谓中断方式,就是串口收/发标志位出发中断后,在中断中执行既定操作,可通过函数调用来实现. 接收 ...
- 51单片机 时钟显示、设置闹钟功能的实现 (附详细算法思路、proteus电路图)
功能要求: 1.利用定时器中断实现时钟功能,格式:时-分-秒. 2.实现时钟显示和闹钟设置两个功能的切换. 3.闹钟设置,且限定字符格式(如时针不得超过24等). 4.时钟到达预设值时,闹铃正常响起, ...
- 51单片机时钟(闹钟)
题目要求 用按键设定时钟的时.分.秒.要求用4键方式,即选择.加.减.确认键,选择键用于选择修改起始时.分.秒值,每按一次,被修改数码管顺序移动并闪烁.用+,- 键修改数值,确认键确定修改结束. 用扫 ...
- 单片机第13课:串口通信---向计算机发送数据
JP3接P0口. #include<reg51.h> #define uchar unsigned char uchar flag,num; // void initSer(); void ...
- 易语言和c51通信,51单片机与PC上位机串口通信之LED控制
#include #define uint8 unsigned char #define uint16 unsigned int uint8 receive_buffer[6]; ...
- 串口通信-电脑控制单片机点亮LED
前言 此篇只对各函数功能做通俗易懂的解释,适合初学者理解串口通信的功能. 一.串口通信 1.什么是串口通信 我们使用的usb转串口是经典的串口通信之一,实现了电脑与单片机之间的联系,将程序通过串口从电 ...
- 51单片机学习笔记-6串口通信
6 串口通信 [toc] 注:笔记主要参考B站江科大自化协教学视频"51单片机入门教程-2020版 程序全程纯手打 从零开始入门". 注:工程及代码文件放在了本人的Github仓库 ...
- 51单片机:中断系统(外部中断,定时器中断,串口通信)
目录 中断系统简介: 中断的优先级和嵌套: 8个中断请求源及其优先级: 中断的分别介绍: 1.外部中断0:INT0 2.外部中断1 3.T0和 T1:定时计数器的功能 4.串口中断(串口为什么使用定时 ...
- 蓝桥杯单片机串口通信学习提升笔记
今日得以继续蓝桥杯国赛备赛之旅: 有道是 "不知何事萦怀抱,醒也无聊,醉也无聊,梦也何曾到谢桥." 那我们该如何 让这位诗人纳兰 "再听乐府曲 ,畅解相思苦"呢 ...
最新文章
- 海外名校毕业!好不容易凭借超强的面试能力+算法入职的谷歌新员工被批干活太慢,委屈得要哭!作为职场新人该怎么办?...
- 最新发现6个高质量网站,让人眼前一亮!
- python中使用 protocol buffer(Protobuf)
- 通过sqlplus执行*.sql文件时常见的问题总结
- 读郭老师推荐书籍--《原则》
- 网络光端机产品特点及实际应用范围详解
- MIUI10迎来最后一波开发版推送 用户体验再升级
- vs2005中的aspnetdb(转)
- 数据库修复工具 - DatabaseCompressor 之从9M到900K+
- 大数计算器c语言实训报告,C语言计算器设计实验报告.doc
- 艾宾浩斯记忆表格excel_艾宾浩斯打卡群第二期邀请函
- 【AI视野·今日NLP 自然语言处理论文速览 第三十三期】Thu, 21 Apr 2022
- cesium导入骨骼动画
- USYD悉尼大学DATA1002 详细作业解析Module6
- php获取应用宝app下载连接
- Java-学校项目3---类与对象
- dhcp应该开启还是关闭(dhcp应该开启还是关闭)
- 在 Jenkins 上轻松重用 Tekton 和 Jenkins X
- 机器学习常见损失函数,二元交叉熵,类别交叉熵,MSE,稀疏类别交叉熵
- ccf-csp 2015春季真题题解