单片机 > 单片机程序设计 > 详情

51单片机之大杂烩

发布时间:2024-11-04 发布时间:
|
  1. /************************************************************ 

  2.     程序实现的功能: 

  3.         用矩阵按键控制 8*8 LED 点阵和数码管, 

  4.     实现按下1到9的数字键数码管从100或200。。。或900的 

  5.     倒计时,一秒钟减1,直到减到0为止。 

  6.     同时LED点阵以呼吸灯的方式渐明渐暗,显示“王”字, 

  7.     当按下数字键0时,LED点阵关闭,同时数码管停止计数 

  8.     并显示结果。 

  9.  

  10.     作者:宁静致远 

  11. ************************************************************/  

  12. #include   

  13.   

  14. typedef unsigned char uchar;  

  15. typedef unsigned int uint;  

  16. typedef unsigned long ulong;  

  17.   

  18. sbit ADDR0 = P1^0;  

  19. sbit ADDR1 = P1^1;  

  20. sbit ADDR2 = P1^2;  

  21. sbit ADDR3 = P1^3;  

  22. sbit ENLED = P1^4;  

  23.   

  24. sbit KEY_OUT_3 = P2^0;  

  25. sbit KEY_OUT_2 = P2^1;  

  26. sbit KEY_OUT_1 = P2^2;  

  27. sbit KEY_OUT_0 = P2^3;  

  28. sbit KEY_IN_0 = P2^4;  

  29. sbit KEY_IN_1 = P2^5;  

  30. sbit KEY_IN_2 = P2^6;  

  31. sbit KEY_IN_3 = P2^7;  

  32.   

  33. ulong periodCnt = 0;  //PWM周期计数值  

  34. uchar highRH = 0;  //高电平重载值的高字节  

  35. uchar highRL = 0;  //高电平重载值的低字节  

  36. uchar lowRH  = 0;  //低电平重载值的高字节  

  37. uchar lowRL  = 0;  //低电平重载值的低字节  

  38. uchar sumRH = 0;  

  39. uchar sumRL = 0;  

  40. uchar T1RH = 0;    //T1重载值的高字节  

  41. uchar T1RL = 0;    //T1重载值的低字节  

  42. bit enChange = 1;  

  43. bit enLED1 = 1;  

  44. uint rate, rate2Cnt;  

  45. uint numberShow = 100;  

  46.   

  47. uchar code dutyCycle[13] = {  //占空比调整表  

  48.     5, 18, 30, 41, 51, 60, 68, 75, 81, 86, 90, 93, 95  

  49. };  

  50. uchar pdata hRHi[13], pdata hRLi[13], pdata lRHi[13], pdata lRLi[13];  

  51. uchar code image[8] = {  

  52.     0x81,0x81,0xE7,0xC3,0xC3,0xE7,0x81,0x81  

  53. };  

  54. uchar code LEDChar[] = {  //数码管显示字符转换表  

  55.     0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,  

  56.     0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E  

  57. };  

  58. uchar LEDBuff[6] = {  //数码管显示缓冲区  

  59.     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF  

  60. };  

  61. uchar code keyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表  

  62.     {0x31, 0x32, 0x33, 0x26}, //数字键1、数字键2、数字键3、向上键  

  63.     {0x34, 0x35, 0x36, 0x25}, //数字键4、数字键5、数字键6、向左键  

  64.     {0x37, 0x38, 0x39, 0x28}, //数字键7、数字键8、数字键9、向下键  

  65.     {0x30, 0x1B, 0x0D, 0x27}  //数字键0、ESC键、  回车键、 向右键  

  66. };  

  67. uchar keyState[4][4] = {  //全部矩阵按键的当前状态  

  68.     {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1}  

  69. };  

  70.   

  71. void configTmr0(uint fr, uchar dc);  

  72. void configTmr1(uint ms1, uchar ms2);  

  73. void calcRldVal(uchar idx);  

  74. void keyScan();  

  75. void keyAction(uchar keyCode);  

  76. void keyDriver();  

  77.   

  78. void main() {  

  79.     uchar i;  

  80.   

  81.     EA = 1;     //开总中断  

  82.     PT0 = 1;    //设置T0抢占优先  

  83.     ADDR3 = 0;  //选中LED点阵  

  84.     ENLED = 0;  

  85.     configTmr0(1000, dutyCycle[0]);  //配置并启动PWM  

  86.     for (i = 0; i 

  87.         calcRldVal(i);  

  88.     configTmr1(50, 1);  

  89.     while (1) {  

  90.         keyDriver();  

  91.     }  

  92. }  

  93. //配置并启动T1,ms1:呼吸灯的变化间隔,ms2:矩阵按键的扫描间隔(T1溢出时间)  

  94. void configTmr1(uint ms1, uchar ms2) {  

  95.     ulong tmp;  //临时变量  

  96.   

  97.     rate = ms1 / ms2;  

  98.     tmp = 11059200 / 12;      //定时器计数频率  

  99.     tmp = (tmp * ms2) / 1000;  //计算所需的计数值  

  100.     tmp = 65536 - tmp;        //计算定时器重载值  

  101.     tmp = tmp + 12;           //补偿中断响应延时造成的误差  

  102.     T1RH = tmp >> 8;  //定时器重载值拆分为高低字节  

  103.     T1RL = tmp;  

  104.   

  105.     TMOD &= 0x0F;   //清零T1的控制位  

  106.     TMOD |= 0x10;   //配置T1为模式1  

  107.     TH1 = T1RH;     //加载T1重载值  

  108.     TL1 = T1RL;  

  109.     ET1 = 1;        //使能T1中断  

  110.     TR1 = 1;        //启动T1  

  111. }  

  112. /* 配置并启动PWM,fr-频率,dc-占空比 */  

  113. void configTmr0(uint fr, uchar dc) {  

  114.     uint high, low, sum;  

  115.   

  116.     rate2Cnt = fr - 1;      //到达1秒所需的计数值  

  117.   

  118.     periodCnt = 11059200 / 12 / fr; //计算一个周期所需的计数值  

  119.     high = periodCnt * dc / 100;    //计算高电平所需的计数值  

  120.     low  = periodCnt - high;        //计算低电平所需的计数值  

  121.     high = 65536L - high + 12;       //计算高电平的定时器重载值并补偿中断延时  

  122.     low  = 65536L - low  + 12;       //计算低电平的定时器重载值并补偿中断延时  

  123.     sum = 65536L - periodCnt + 12;  

  124.   

  125.     highRH = high >> 8; //高电平重载值拆分为高低字节  

  126.     highRL = high;  

  127.     lowRH  = low >> 8;  //低电平重载值拆分为高低字节  

  128.     lowRL  = low;  

  129.     sumRH = sum >> 8;  

  130.     sumRL = sum;  

  131.   

  132.     TMOD &= 0xF0;   //清零T0的控制位  

  133.     TMOD |= 0x01;   //配置T0为模式1  

  134.     TH0 = highRH;   //加载T0重载值  

  135.     TL0 = highRL;  

  136.     ET0 = 1;        //使能T0中断  

  137.     TR0 = 1;        //启动T0  

  138. }  

  139.   

  140. void calcRldVal(uchar idx) {  

  141.     uint  high, low;  

  142.   

  143.     high = periodCnt * dutyCycle[idx] / 100;    //计算高电平所需的计数值  

  144.     low  = periodCnt - high;        //计算低电平所需的计数值  

  145.     high = 65536L - high + 12;       //计算高电平的定时器重载值并补偿中断延时  

  146.     low  = 65536L - low  + 12;       //计算低电平的定时器重载值并补偿中断延时  

  147.     hRHi[idx] = high >> 8; //高电平重载值拆分为高低字节  

  148.     hRLi[idx] = high;  

  149.     lRHi[idx] = low >> 8;  //低电平重载值拆分为高低字节  

  150.     lRLi[idx] = low;  

  151. }  

  152. /* 

  153. #define LED1_Scan(); {   

  154.     static uchar i = 0;  

  155.     P0 = 0xFF;   

  156.     P1 = (P1 & 0xF8) | i;    

  157.     P0 = image[i];   

  158.     i = ++i & 0x07;  

  159.  

  160. #define LED2_Scan(); {   

  161.     static uchar i = 0;  

  162.     P0 = 0xFF;   

  163.     P1 = (P1 & 0xF8) | i;    

  164.     P0 = LEDBuff[i];     

  165.     if (i 

  166.         i++;     

  167.     else     

  168.         i = 0;   

  169. */  

  170. void keyScan() {  

  171.     static uchar i = 0;  

  172.     static uchar keyBuf[4][4] = {  

  173.         {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},  

  174.         {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}  

  175.     };  

  176.     uchar j;  

  177.   

  178.     keyBuf[i][0] = (keyBuf[i][0] <

  179.     keyBuf[i][1] = (keyBuf[i][1] <

  180.     keyBuf[i][2] = (keyBuf[i][2] <

  181.     keyBuf[i][3] = (keyBuf[i][3] <

  182.     for (j=0; j<4; j++) {  

  183.         if (keyBuf[i][j] == 0x00)  

  184.             keyState[i][j] = 0;  

  185.         else if (keyBuf[i][j] == 0xFF)  

  186.             keyState[i][j] = 1;  

  187.     }  

  188.     switch (i) {  

  189.         case 0: KEY_OUT_0 = 1; KEY_OUT_1 = 0; break;  

  190.         case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;  

  191.         case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;  

  192.         case 3: KEY_OUT_3 = 1; KEY_OUT_0 = 0; break;  

  193.         default : break;  

  194.     }  

  195.     i = ++i & 0x03;  

  196. }  

  197.   

  198. #define resetLEDBuff(num); {      

  199.     LEDBuff[0] = LEDChar[(num)%10];     

  200.     LEDBuff[1] = LEDChar[(num)/10%10];      

  201.     LEDBuff[2] = LEDChar[(num)/100%10];     

  202. }  

  203.   

  204. void keyAction(uchar keyCode) {  

  205.     if (keyCode == 0x30) {  

  206.         enChange = 0;  

  207.         //TR0 = 0;  

  208.         enLED1 = 0;  

  209.     }  

  210.     else if (keyCode >= 0x31 && keyCode <= 0x39) {  

  211.         enChange = 1;  

  212.         //TR0 = 1;  

  213.         enLED1 = 1;  

  214.         numberShow = (keyCode - 0x30) * 100;  

  215.         resetLEDBuff(numberShow);  

  216.     }  

  217. }  

  218.   

  219. void keyDriver() {  

  220.     uchar i, j;  

  221.     static uchar backup[4][4] = {  

  222.         {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}  

  223.     };  

  224.   

  225.     for (i=0; i<4; i++)  

  226.         for (j=0; j<4; j++)  

  227.             if (keyState[i][j] != backup[i][j]) {  

  228.                 if (keyState[i][j] == 0)  

  229.                     keyAction(keyCodeMap[i][j]);  

  230.                 backup[i][j] = keyState[i][j];  

  231.             }  

  232. }  

  233. //定时器T0的中断服务函数,完成LED点阵的扫描,数码管的扫描,数码管显示的动态调整  

  234. //和产生PWM输出  

  235. void interruptTmr0() interrupt 1 {  

  236.     static bit *** = 1;  

  237.     static uchar idx = 0;  

  238.     static uint cnt2 = 0;  

  239.   

  240.     if (ADDR3) {  

  241.         TH0 = sumRH;  

  242.         TL0 = sumRL;  

  243.   

  244.         P0 = 0xFF;  

  245.         P1 = (P1 & 0xF8) | idx;  

  246.         P0 = LEDBuff[idx];  

  247.   

  248.         if (cnt2 == rate2Cnt) {  

  249.             if (enChange) {  

  250.                 if (numberShow > 0) {  

  251.                     numberShow--;  

  252.                     resetLEDBuff(numberShow);  

  253.                 }  

  254.             }  

  255.             cnt2 = 0;  

  256.         }  

  257.         else  

  258.             cnt2++;  

  259.   

  260.         if (idx 

  261.             idx++;  

  262.         else {  

  263.             idx = 0;  

  264.             ADDR3 = 0;  

  265.         }  

  266.     }  

  267.     else {  

  268.         if (***) {  

  269.             TH0 = lowRH;  

  270.             TL0 = lowRL;  

  271.             if (enLED1) {  

  272.                 P0 = 0xFF;  

  273.                 P1 = (P1 & 0xF8) | idx;  

  274.                 P0 = image[idx];  

  275.             }  

  276.             *** = 0;  

  277.         }  

  278.         else {  

  279.             TH0 = highRH;  

  280.             TL0 = highRL;  

  281.             P0 = 0xFF;  

  282.             *** = 1;  

  283.             if (idx 

  284.                 idx++;  

  285.             else {  

  286.                 idx = 0;  

  287.                 ADDR3 = 1;  

  288.             }  

  289.         }  

  290.     }  

  291. }  

  292. //定时器T1的中断服务函数,完成矩阵按键的扫描,定时动态调整占空比  

  293. void interruptTimer1() interrupt 3 {  

  294.     static bit dir = 0;  

  295.     static uchar index = 0;  

  296.     static uint cnt = 0;  

  297.   

  298.     TH1 = T1RH;  //重新加载T1重载值  

  299.     TL1 = T1RL;  

  300.     keyScan();  

  301.     if (cnt == rate) {  

  302.         highRH = hRHi[index];  

  303.         highRL = hRLi[index];  

  304.         lowRH = lRHi[index];  

  305.         lowRL = lRLi[index];  

  306.         cnt = 0;  

  307.     }  

  308.     else  

  309.         cnt++;  

  310.   

  311.     if (dir == 0) {  

  312.         index++;  

  313.         if (index == 12)  

  314.             dir = 1;  

  315.     }  

  316.     else {  

  317.         index--;  

  318.         if (index == 0)  

  319.             dir = 0;  

  320.     }  

  321. }  



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
MSP430低功耗模式-while循环失效