51单片机之大杂烩
来源:互联网 发布:finale2016打谱软件 编辑:程序博客网 时间:2024/06/04 18:04
/************************************************************ 程序实现的功能: 用矩阵按键控制 8*8 LED 点阵和数码管, 实现按下1到9的数字键数码管从100或200。。。或900的 倒计时,一秒钟减1,直到减到0为止。 同时LED点阵以呼吸灯的方式渐明渐暗,显示“王”字, 当按下数字键0时,LED点阵关闭,同时数码管停止计数 并显示结果。 作者:宁静致远************************************************************/#include <reg52.h>typedef unsigned char uchar;typedef unsigned int uint;typedef unsigned long ulong;sbit ADDR0 = P1^0;sbit ADDR1 = P1^1;sbit ADDR2 = P1^2;sbit ADDR3 = P1^3;sbit ENLED = P1^4;sbit KEY_OUT_3 = P2^0;sbit KEY_OUT_2 = P2^1;sbit KEY_OUT_1 = P2^2;sbit KEY_OUT_0 = P2^3;sbit KEY_IN_0 = P2^4;sbit KEY_IN_1 = P2^5;sbit KEY_IN_2 = P2^6;sbit KEY_IN_3 = P2^7;ulong periodCnt = 0; //PWM周期计数值uchar highRH = 0; //高电平重载值的高字节uchar highRL = 0; //高电平重载值的低字节uchar lowRH = 0; //低电平重载值的高字节uchar lowRL = 0; //低电平重载值的低字节uchar sumRH = 0;uchar sumRL = 0;uchar T1RH = 0; //T1重载值的高字节uchar T1RL = 0; //T1重载值的低字节bit enChange = 1;bit enLED1 = 1;uint rate, rate2Cnt;uint numberShow = 100;uchar code dutyCycle[13] = { //占空比调整表5, 18, 30, 41, 51, 60, 68, 75, 81, 86, 90, 93, 95};uchar pdata hRHi[13], pdata hRLi[13], pdata lRHi[13], pdata lRLi[13];uchar code image[8] = { 0x81,0x81,0xE7,0xC3,0xC3,0xE7,0x81,0x81};uchar code LEDChar[] = { //数码管显示字符转换表 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E};uchar LEDBuff[6] = { //数码管显示缓冲区 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};uchar code keyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表 {0x31, 0x32, 0x33, 0x26}, //数字键1、数字键2、数字键3、向上键 {0x34, 0x35, 0x36, 0x25}, //数字键4、数字键5、数字键6、向左键 {0x37, 0x38, 0x39, 0x28}, //数字键7、数字键8、数字键9、向下键 {0x30, 0x1B, 0x0D, 0x27} //数字键0、ESC键、 回车键、 向右键};uchar keyState[4][4] = { //全部矩阵按键的当前状态 {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};void configTmr0(uint fr, uchar dc);void configTmr1(uint ms1, uchar ms2);void calcRldVal(uchar idx);void keyScan();void keyAction(uchar keyCode);void keyDriver();void main() {uchar i; EA = 1; //开总中断 PT0 = 1; //设置T0抢占优先 ADDR3 = 0;//选中LED点阵ENLED = 0;configTmr0(1000, dutyCycle[0]); //配置并启动PWMfor (i = 0; i < 13; i++) calcRldVal(i); configTmr1(50, 1); while (1) { keyDriver(); }}//配置并启动T1,ms1:呼吸灯的变化间隔,ms2:矩阵按键的扫描间隔(T1溢出时间)void configTmr1(uint ms1, uchar ms2) { ulong tmp; //临时变量 rate = ms1 / ms2; tmp = 11059200 / 12; //定时器计数频率 tmp = (tmp * ms2) / 1000; //计算所需的计数值 tmp = 65536 - tmp; //计算定时器重载值 tmp = tmp + 12; //补偿中断响应延时造成的误差 T1RH = tmp >> 8; //定时器重载值拆分为高低字节 T1RL = tmp; TMOD &= 0x0F; //清零T1的控制位 TMOD |= 0x10; //配置T1为模式1 TH1 = T1RH; //加载T1重载值 TL1 = T1RL; ET1 = 1; //使能T1中断 TR1 = 1; //启动T1}/* 配置并启动PWM,fr-频率,dc-占空比 */void configTmr0(uint fr, uchar dc) { uint high, low, sum; rate2Cnt = fr - 1;//到达1秒所需的计数值 periodCnt = 11059200 / 12 / fr; //计算一个周期所需的计数值 high = periodCnt * dc / 100; //计算高电平所需的计数值 low = periodCnt - high; //计算低电平所需的计数值 high = 65536L - high + 12; //计算高电平的定时器重载值并补偿中断延时 low = 65536L - low + 12; //计算低电平的定时器重载值并补偿中断延时 sum = 65536L - periodCnt + 12; highRH = high >> 8; //高电平重载值拆分为高低字节 highRL = high; lowRH = low >> 8; //低电平重载值拆分为高低字节 lowRL = low; sumRH = sum >> 8; sumRL = sum; TMOD &= 0xF0; //清零T0的控制位 TMOD |= 0x01; //配置T0为模式1 TH0 = highRH; //加载T0重载值 TL0 = highRL; ET0 = 1; //使能T0中断 TR0 = 1; //启动T0}void calcRldVal(uchar idx) { uint high, low; high = periodCnt * dutyCycle[idx] / 100; //计算高电平所需的计数值 low = periodCnt - high; //计算低电平所需的计数值 high = 65536L - high + 12; //计算高电平的定时器重载值并补偿中断延时 low = 65536L - low + 12; //计算低电平的定时器重载值并补偿中断延时 hRHi[idx] = high >> 8; //高电平重载值拆分为高低字节 hRLi[idx] = high; lRHi[idx] = low >> 8; //低电平重载值拆分为高低字节 lRLi[idx] = low;}/*#define LED1_Scan(); { \ static uchar i = 0; \ P0 = 0xFF; \ P1 = (P1 & 0xF8) | i; \ P0 = image[i]; \ i = ++i & 0x07; \}#define LED2_Scan(); { \ static uchar i = 0; \ P0 = 0xFF; \ P1 = (P1 & 0xF8) | i; \ P0 = LEDBuff[i]; \ if (i < 5) \ i++; \ else \ i = 0; \}*/void keyScan() { static uchar i = 0; static uchar keyBuf[4][4] = { {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF} }; uchar j; keyBuf[i][0] = (keyBuf[i][0] << 1) | KEY_IN_0; keyBuf[i][1] = (keyBuf[i][1] << 1) | KEY_IN_1; keyBuf[i][2] = (keyBuf[i][2] << 1) | KEY_IN_2; keyBuf[i][3] = (keyBuf[i][3] << 1) | KEY_IN_3; for (j=0; j<4; j++) { if (keyBuf[i][j] == 0x00) keyState[i][j] = 0; else if (keyBuf[i][j] == 0xFF) keyState[i][j] = 1; } switch (i) { case 0: KEY_OUT_0 = 1; KEY_OUT_1 = 0; break; case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break; case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break; case 3: KEY_OUT_3 = 1; KEY_OUT_0 = 0; break; default : break; } i = ++i & 0x03;}#define resetLEDBuff(num); { \ LEDBuff[0] = LEDChar[(num)%10]; \ LEDBuff[1] = LEDChar[(num)/10%10]; \ LEDBuff[2] = LEDChar[(num)/100%10]; \}void keyAction(uchar keyCode) { if (keyCode == 0x30) { enChange = 0; //TR0 = 0;enLED1 = 0; } else if (keyCode >= 0x31 && keyCode <= 0x39) { enChange = 1; //TR0 = 1;enLED1 = 1; numberShow = (keyCode - 0x30) * 100; resetLEDBuff(numberShow); }}void keyDriver() { uchar i, j; static uchar backup[4][4] = { {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1} }; for (i=0; i<4; i++) for (j=0; j<4; j++) if (keyState[i][j] != backup[i][j]) { if (keyState[i][j] == 0) keyAction(keyCodeMap[i][j]); backup[i][j] = keyState[i][j]; }}//定时器T0的中断服务函数,完成LED点阵的扫描,数码管的扫描,数码管显示的动态调整//和产生PWM输出void interruptTmr0() interrupt 1 { static bit flg = 1; static uchar idx = 0; static uint cnt2 = 0; if (ADDR3) { TH0 = sumRH; TL0 = sumRL; P0 = 0xFF; P1 = (P1 & 0xF8) | idx; P0 = LEDBuff[idx]; if (cnt2 == rate2Cnt) { if (enChange) { if (numberShow > 0) { numberShow--; resetLEDBuff(numberShow); } } cnt2 = 0; } else cnt2++; if (idx < 5) idx++; else { idx = 0; ADDR3 = 0; } } else { if (flg) { TH0 = lowRH; TL0 = lowRL;if (enLED1) { P0 = 0xFF; P1 = (P1 & 0xF8) | idx; P0 = image[idx];} flg = 0; } else { TH0 = highRH; TL0 = highRL; P0 = 0xFF; flg = 1;if (idx < 7)idx++;else {idx = 0;ADDR3 = 1;} } }}//定时器T1的中断服务函数,完成矩阵按键的扫描,定时动态调整占空比void interruptTimer1() interrupt 3 { static bit dir = 0; static uchar index = 0; static uint cnt = 0; TH1 = T1RH; //重新加载T1重载值 TL1 = T1RL; keyScan(); if (cnt == rate) { highRH = hRHi[index]; highRL = hRLi[index]; lowRH = lRHi[index]; lowRL = lRLi[index]; cnt = 0; } else cnt++; if (dir == 0) { index++; if (index == 12) dir = 1; } else { index--; if (index == 0) dir = 0; }}
0 0
- 51单片机之大杂烩
- 51单片机之大杂烩
- 大杂烩2之乱七八糟
- 51单片机之计时器
- 51单片机之数码管
- 51单片机之定时器
- 大杂烩
- 大杂烩
- 大杂烩
- 大杂烩
- 大杂烩
- 大杂烩
- 大杂烩
- 大杂烩
- 大杂烩
- 大杂烩
- 大杂烩
- 大杂烩
- netperf 网络性能测量
- ADB端口被占用
- storyboard view之间传值swift
- Android:新浪微博拉起客户端分享——完美实现同时分享图片和文字(Intent.ACTION_SEND)
- utl_file包的使用
- 51单片机之大杂烩
- XCode 快捷键
- Eclipse中注释复用
- 在Java应用中使用BeanShell(2.0b41)的简单示例
- 关于block的实现和注意
- android enter 隐藏输入法
- JSP内置对象request中的getParameter()和getAttribute()方法的区别
- Font Awesome 4.2.0 Icon
- gnome-logs开发记录3--修复bug726228+杂记