![]() |
中国面包师贴吧-楼主(阅:912/回:0)通过232串口设置MSP430F149IPM单片机液晶显示时间的程序通过232串口设置MSP430F149IPM单片机液晶显示时间的程序 下面介绍一段通过232串口设置MSP430F149IPM单片机液晶显示时间的程序。用户通过串口发送0X01,0X02,0X03,0X04可以改变单片机液晶显示时间,当到达一定设置时间时,单片机P2端口输出7路高电平,1路低电平, 第二段程序,可以从单片机按键像计算机232串口发送0x00,同时单片机液晶屏显示时间。 MSP430单片机电路如下,程序通过IAR430V5.3软件编译通过,生成.txt文件,使用BSL下载软件-Msp430BSL 通过USB端口把.TXT文件烧写到单片机中。程序和电路可以在下面的网址下载:链接:https://pan.baidu.com/s/1PxUz7CXQP7hGBTIDc7kUog ; 提取码:2kcy 链接:https://pan.baidu.com/s/1e1uS02vlUWDhMH1TnZUEYw ; 提取码:kuw9 https://share.weiyun.com/5PIcLM9 程序1: /***************************************************** 程序功能:在1602液晶上显示用MCU的TimerA模拟的数字 式实时时钟。 测试说明:观察液晶显示 程序功能:接收来自PC机的字符,然后重新发送给PC机 程序功能:串口发送十六进制数01,液晶显示时间25:25:25, 串口发送十六进制数02,液晶显示时间35:35:35, 串口发送十六进制数03,液晶显示时间11:11:34, 液晶计时11:10:60时,P2口输出01111111,液晶显示33:33:11 通信格式:N.8.1, 9600 无校验,8个数据位,1个停止位,波特率9600 *****************************************************/ #include <msp430x14x.h> #include “cry1602.h” #include “clock.h” #include “cry1602.c” #include “clock.c” #define keyin P3IN uchar tishi[]={“Current Time is”}; //提示信息 void delay(void); extern uchar second,minute,hour,hour0; extern uchar pmin,phour,ps1; #define SetTime(H,M,S) {second=S;minute=M;hour=H;hour0=H;} uchar scandata[16] ; /*主函数/ void main(void) { /*下面六行程序关闭所有的IO口*/ P1DIR = 0XFF;P1OUT = 0XFF; P2DIR = 0XFF;P2OUT = 0XFF; P3DIR = 0XFF;P3OUT = 0XFF; P4DIR = 0XFF;P4OUT = 0XFF; P5DIR = 0XFF;P5OUT = 0XFF; P6DIR = 0XFF;P6OUT = 0XFF; WDTCTL = WDTPW + WDTHOLD; //关闭看门狗 1 2 3 4 5 6 7 8 9 // P6DIR |= BIT2;P6OUT |= BIT2;//关闭电平转换 // P6DIR |= BIT6;P6OUT &= ~BIT6;//关闭电平转换 P3SEL |= 0x30; // 选择P3.4和P3.5做UART通信端口 ME1 |= UTXE0 + URXE0; // 使能USART0的发送和接受 UCTL0 |= CHAR; // 选择8位字符 UTCTL0 |= SSEL0; // UCLK = ACLK UBR00 = 0x03; // 波特率9600 UBR10 = 0x00; // UMCTL0 = 0x4A; // Modulation UCTL0 &= ~SWRST; // 初始化UART状态机 // IE1 |= URXIE0; // 使能USART0的接收中断 CCR0 = 32768 - 1; //设置定时器A的中断时间为1S TACTL = TASSEL_1 + MC_1; //计数时钟ACLK, 增计数模式 CCTL0 |= CCIE; //使能CCR0比较中断 _EINT(); //打开全局中断 // IE1 |= URXIE0; // 使能USART0的接收中断 //请在此处设置正确时间 SetTime(11,11,34); //顺序:时,分,秒,格式:BCD码 LcdReset(); DispNChar(0,0,15,tishi); //显示提示文字 Disp1Char(6,1,':'); //显示字符 : Disp1Char(9,1,':'); P2DIR = 0xff; //设置P2口方向为输出 // SetTime( RXBUF0, RXBUF0, RXBUF0); // P2OUT = 0x40; // if(IFG1 & URXIFG0) //如果收到字符 // { //SetTime( RXBUF0, RXBUF0, RXBUF0); //顺序:时,分,秒,格式:BCD码 // } //else // { // SetTime(11,11,34); //顺序:时,分,秒,格式:BCD码 //} while(1) { // _EINT(); //打开全局中断 // LPM1; //进入LPM1模式 // while (!(IFG1 & UTXIFG0)); //等待以前的字符发送完毕 // TXBUF0 = RXBUF0; //将收到的字符发送出去 // if(IFG1 & URXIFG0) //如果收到字符 //{ // switch(RXBUF0) // { //case 0x01: if(RXBUF0 == 0x01) //如果是第一个按键被按下 { second=25; minute=25; hour=25; //SetTime(19,19,19); TXBUF0 = RXBUF0; // } //} } if(RXBUF0 == 0x02) //如果是第一个按键被按下 { second=35; minute=35; hour=35; //SetTime(19,19,19); TXBUF0 = RXBUF0; // } //} } if(RXBUF0 == 0x03) //如果是第一个按键被按下 { second=34; minute=11; hour=11; //SetTime(19,19,19); TXBUF0 = RXBUF0; // } //} } // else // { // SetTime(11,11,34); //顺序:时,分,秒,格式:BCD码 // } //scandata[16] =RXBUF0; // if(RXBUF0!=0X00) // { // SetTime( RXBUF0, RXBUF0, RXBUF0); //顺序:时,分,秒,格式:BCD码 // } //LPM3; //进入LPM3低功耗模式 Display(); if(second == 60&minute==10&hour==11) //如果是第一个按键被按下 { P2OUT = 0x80; SetTime(33,33,11); } if(keyin == 0xbf) //如果是第一个按键被按下 { delay(); if(keyin == 0xbf) { while(keyin != 0xbf); //等待按键放开 SetTime(22,22,11); //顺序:时,分,秒,格式:BCD码 return; } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 } /******************************************* 函数名称:TimerA_ISR 功 能:定时器A的中断服务函数 参 数:无 返回值 :无 ********************************************/ #pragma vector=TIMERA0_VECTOR __interrupt void TimerA_ISR(void) { Clock(); LPM3_EXIT; } void delay(void) { uint tmp; for(tmp = 12000;tmp > 0;tmp--); 1 } /******************************************* 函数名称:UART0_RXISR 功 能:UART0的接收中断服务函数,在这里唤醒 CPU,使它退出低功耗模式 参 数:无 返回值 :无 ********************************************/ #pragma vector = UART0RX_VECTOR __interrupt void UART0_RXISR(void) { LPM1_EXIT; //退出低功耗模式 } //#include <msp430x44x.h> #include “cry1602.h” /全局变量**/ uchar second,minute,hour,hour0; //秒、分、时变量 uchar pmin,phour,ps1; //辅助计算变量 /******************************************* 函数名称:Clock 功 能:计算当前时间 参 数:无 返回值 :无 说明 :本函数对本文件开头定义的second,minute, hour,hour0四个全局变量进行操作 */ void Clock(void) { second -= 1; // second<=60& second>=0; // minute<=60&minute>=0; // hour<=100&hour>=0; if(second == 0) { second = 60; minute -= 1; if(minute == 0) { minute = 60; hour -= 1; hour0 -= 1; if(hour == 0) hour = 24; } } } //void Clock(void) //{ // second -= 1; // second<=60& second>=0; // minute<=60&minute>=0; // hour<=100&hour>=0; //if(second == 60) // { // second = 0; // minute -= 1; //if(minute == 60) //{ // minute = 0; // hour -= 1; hour0 -= 1; // if(hour == 24) hour = 0; //} // } //} / 函数名称:Display 功 能:在1602液晶上显示时间 参 数:无 返回值 :无 说明 :本函数对本文件开头定义的全局变量进行 操作 ********************************************/ void Display(void) { uchar s0,s1; uchar m0,m1; uchar h0,h1; s1 = second / 10; //十位 s0 = second - (s1 * 10); //个位 s1 += 48; //加上48等于其对应的ASCII码 s0 += 48; Disp1Char(11,1,s0); 1 2 3 4 5 6 if(ps1 != s1) { ps1 = s1; Disp1Char(10,1,s1); } if(pmin != minute) 1 { pmin = minute; m1 = minute / 10; m0 = minute - (m1 * 10); m1 += 48; m0 += 48; Disp1Char(7,1,m1); Disp1Char(8,1,m0); } if(phour != hour) { phour = hour; h1 = hour / 10; h0 = hour - (h1 * 10); h1 += 48; h0 += 48; Disp1Char(4,1,h1); Disp1Char(5,1,h0); } } void Clock(void); void Display(void); #include <msp430x14x.h> #include “cry1602.h” typedef unsigned char uchar; typedef unsigned int uint; /宏定义*/ #define DataDir P2DIR #define DataPort P2OUT #define Busy 0x80 #define CtrlDir P6DIR #define CLR_RS P6OUT&=~BIT3; //RS = P3.0 #define SET_RS P6OUT|=BIT3; #define CLR_RW P6OUT&=~BIT4;//RW = P3.1 #define SET_RW P6OUT|=BIT4; #define CLR_EN P6OUT&=~BIT5;//EN = P3.2 #define SET_EN P6OUT|=BIT5; /******************************************* 函数名称:DispNchar 功 能:让液晶从某个位置起连续显示N个字符 参 数:x–位置的列坐标 y–位置的行坐标 n–字符个数 ptr–指向字符存放位置的指针 返回值 :无 ********************************************/ void DispNChar(uchar x,uchar y, uchar n,uchar *ptr) { uchar i; for (i=0;i<n;i++) { Disp1Char(x++,y,ptr[i]); if (x == 0x0f) { x = 0; y ^= 1; } } 1 2 3 4 5 6 7 8 9 } /******************************************* 函数名称:LocateXY 功 能:向液晶输入显示字符位置的坐标信息 参 数:x–位置的列坐标 y–位置的行坐标 返回值 :无 ********************************************/ void LocateXY(uchar x,uchar y) { uchar temp; temp = x&0x0f; y &= 0x01; if(y) temp |= 0x40; //如果在第2行 temp |= 0x80; LcdWriteCommand(temp,1); 1 2 3 4 5 6 } /******************************************* 函数名称:Disp1Char 功 能:在某个位置显示一个字符 参 数:x–位置的列坐标 y–位置的行坐标 data–显示的字符数据 返回值 :无 */ void Disp1Char(uchar x,uchar y,uchar data) { LocateXY( x, y ); LcdWriteData( data ); } / 函数名称:LcdReset 功 能:对1602液晶模块进行复位操作 参 数:无 返回值 :无 ********************************************/ void LcdReset(void) { CtrlDir |= 0x38; //控制线端口设为输出状态 DataDir = 0xFF; //数据端口设为输出状态 LcdWriteCommand(0x38, 0); //规定的复位操作 Delay5ms(); LcdWriteCommand(0x38, 0); Delay5ms(); LcdWriteCommand(0x38, 0); Delay5ms(); LcdWriteCommand(0x38, 1);//显示模式设置 LcdWriteCommand(0x08, 1);//显示关闭 LcdWriteCommand(0x01, 1); //显示清屏 LcdWriteCommand(0x06, 1);//写字符时整体不移动 LcdWriteCommand(0x0c, 1);//显示开,不开游标,不闪烁 1 2 3 4 5 6 7 8 9 10 11 12 } /******************************************* 函数名称:LcdWriteCommand 功 能:向液晶模块写入命令 参 数:cmd–命令, chk–是否判忙的标志,1:判忙,0:不判 返回值 :无 ********************************************/ void LcdWriteCommand(uchar cmd,uchar chk) { if (chk) WaitForEnable(); // 检测忙信号? CLR_RS; CLR_RW; _NOP(); DataPort = cmd; //将命令字写入数据端口 _NOP(); SET_EN; //产生使能脉冲信号 _NOP(); _NOP(); CLR_EN; 1 2 3 4 5 6 7 8 9 10 11 12 13 } /******************************************* 函数名称:LcdWriteData 功 能:向液晶显示的当前地址写入显示数据 参 数:data–显示字符数据 返回值 :无 ********************************************/ void LcdWriteData( uchar data ) { WaitForEnable(); //等待液晶不忙 SET_RS; CLR_RW; _NOP(); DataPort = data; //将显示数据写入数据端口 _NOP(); SET_EN; //产生使能脉冲信号 _NOP(); _NOP(); CLR_EN; 1 2 3 4 5 6 7 8 9 10 11 } /******************************************* 函数名称:WaitForEnable 功 能:等待1602液晶完成内部操作 参 数:无 返回值 :无 ********************************************/ void WaitForEnable(void) { P2DIR &= 0x00; //将P4口切换为输入状态 CLR_RS; SET_RW; _NOP(); SET_EN; _NOP(); _NOP(); while((P2IN & Busy)!=0); //检测忙标志 CLR_EN; P2DIR |= 0xFF; //将P4口切换为输出状态 1 2 3 4 5 6 7 8 9 10 11 12 } /******************************************* 函数名称:Delay5ms 功 能:延时约5ms 参 数:无 返回值 :无 */ void Delay5ms(void) { uint i=40000; while (i != 0) { i–; } } / 函数名称:Delay400ms 功 能:延时约400ms 参 数:无 返回值 :无 ********************************************/ void Delay400ms(void) { uchar i=50; uint j; while(i--) { j=7269; while(j--); } 1 2 3 4 5 } void DispNChar(unsigned char x,unsigned char y, unsigned char n,unsigned char *ptr); void LocateXY(unsigned char x,unsigned char y); void Disp1Char(unsigned char x,unsigned char y,unsigned char data); void LcdReset(void); void LcdWriteCommand(unsigned char cmd,unsigned char chk); void LcdWriteData( unsigned char data ); void WaitForEnable(void); void Delay5ms(void); void Delay400ms(void); 第二段程序 #include <msp430x14x.h> typedef unsigned char uchar; typedef unsigned int uint; //unsigned char uchar; //unsigned int uint; /全局变量/ uchar key_Pressed; //按键是否被按下:1–是,0–否 uchar key_val; //存放键值 uchar key_Flag; //按键是否已放开:1–是,0–否 //设置键盘逻辑键值与程序计算键值的映射 uchar key_Map[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; /******************************************* 函数名称:Init_Keypad 功 能:初始化扫描键盘的IO端口 参 数:无 返回值 :无 / void Init_Keypad(void) { P1DIR = 0xf0; //P1.0~P1.3设置为输入状态, P1.4~P1.7设置为输出状态 P1OUT |= 0xf0; // P1.4~P1.7输出高电平 key_Flag = 0; key_Pressed = 0; key_val = 0; } /* Check_Key(),检查按键,确认键值 **/ / 函数名称:Check_Key 功 能:扫描键盘的IO端口,获得键值 参 数:无 返回值 :无 ********************************************/ void Check_Key(void) { uchar row ,col,tmp1,tmp2; tmp1 = 0x80; for(row = 0;row < 4;row++) //行扫描 { P1OUT = 0xf0; //P1.4~P1.7输出全1 P1OUT -= tmp1; //P1.4~p1.7输出四位中有一个为0 tmp1 >>=1; if ((P1IN & 0x0f) < 0x0f) //是否P1IN的P1.0~P1.3中有一位为0 { tmp2 = 0x01; // tmp2用于检测出那一位为0 for(col = 0;col < 4;col++) // 列检测 { if((P1IN & tmp2) == 0x00) // 是否是该列,等于0为是 { key_val = key_Map[row * 4 + col]; // 获取键值 return; // 退出循环 } tmp2 <<= 1; // tmp2右移1位 } } } } /******************************************* 函数名称:delay 功 能:延时约15ms,完成消抖功能 参 数:无 返回值 :无 ********************************************/ void delay() { uint tmp; for(tmp = 12000;tmp > 0;tmp–); } /******************************************* 函数名称:Key_Event 功 能:检测按键,并获取键值 参 数:无 返回值 :无 ********************************************/ void Key_Event(void) { uchar tmp; P1OUT &= 0x00; // 设置P1OUT全为0,等待按键输入 tmp = P1IN; // 获取 p1IN if ((key_Pressed == 0x00)&&((tmp & 0x0f) < 0x0f)) //如果有键按下 { key_Pressed = 1; // 如果有按键按下,设置key_Pressed标识 delay(); //消除抖动 Check_Key(); // 调用check_Key(),获取键值 } else if ((key_Pressed == 1)&&((tmp & 0x0f) == 0x0f)) //如果按键已经释放 { key_Pressed = 0; // 清除key_Pressed标识 key_Flag = 1; // 设置key_Flag标识 } else { _NOP(); } } //#include <msp430x44x.h> #include “cry1602.h” /全局变量**/ uchar second,minute,hour,hour0; //秒、分、时变量 uchar pmin,phour,ps1; //辅助计算变量 /******************************************* 函数名称:Clock 功 能:计算当前时间 参 数:无 返回值 :无 说明 :本函数对本文件开头定义的second,minute, hour,hour0四个全局变量进行操作 */ void Clock(void) { second -= 1; // second<=60& second>=0; // minute<=60&minute>=0; // hour<=100&hour>=0; if(second == 0) { second = 60; minute -= 1; if(minute == 0) { minute = 60; hour -= 1; hour0 -= 1; if(hour == 0) hour = 24; } } } //void Clock(void) //{ // second -= 1; // second<=60& second>=0; // minute<=60&minute>=0; // hour<=100&hour>=0; //if(second == 60) // { // second = 0; // minute -= 1; //if(minute == 60) //{ // minute = 0; // hour -= 1; hour0 -= 1; // if(hour == 24) hour = 0; //} // } //} / 函数名称:Display 功 能:在1602液晶上显示时间 参 数:无 返回值 :无 说明 :本函数对本文件开头定义的全局变量进行 操作 ********************************************/ void Display(void) { uchar s0,s1; uchar m0,m1; uchar h0,h1; s1 = second / 10; //十位 s0 = second - (s1 * 10); //个位 s1 += 48; //加上48等于其对应的ASCII码 s0 += 48; Disp1Char(11,1,s0); 1 2 3 4 5 6 if(ps1 != s1) { ps1 = s1; Disp1Char(10,1,s1); } if(pmin != minute) 1 { pmin = minute; m1 = minute / 10; m0 = minute - (m1 * 10); m1 += 48; m0 += 48; Disp1Char(7,1,m1); Disp1Char(8,1,m0); } if(phour != hour) { phour = hour; h1 = hour / 10; h0 = hour - (h1 * 10); h1 += 48; h0 += 48; Disp1Char(4,1,h1); Disp1Char(5,1,h0); } } void Clock(void); void Display(void); #include <msp430x14x.h> #include “cry1602.h” typedef unsigned char uchar; typedef unsigned int uint; /宏定义*/ #define DataDir P2DIR #define DataPort P2OUT #define Busy 0x80 #define CtrlDir P6DIR #define CLR_RS P6OUT&=~BIT3; //RS = P3.0 #define SET_RS P6OUT|=BIT3; #define CLR_RW P6OUT&=~BIT4;//RW = P3.1 #define SET_RW P6OUT|=BIT4; #define CLR_EN P6OUT&=~BIT5;//EN = P3.2 #define SET_EN P6OUT|=BIT5; /******************************************* 函数名称:DispNchar 功 能:让液晶从某个位置起连续显示N个字符 参 数:x–位置的列坐标 y–位置的行坐标 n–字符个数 ptr–指向字符存放位置的指针 返回值 :无 ********************************************/ void DispNChar(uchar x,uchar y, uchar n,uchar *ptr) { uchar i; for (i=0;i<n;i++) { Disp1Char(x++,y,ptr[i]); if (x == 0x0f) { x = 0; y ^= 1; } } 1 2 3 4 5 6 7 8 9 } /******************************************* 函数名称:LocateXY 功 能:向液晶输入显示字符位置的坐标信息 参 数:x–位置的列坐标 y–位置的行坐标 返回值 :无 ********************************************/ void LocateXY(uchar x,uchar y) { uchar temp; temp = x&0x0f; y &= 0x01; if(y) temp |= 0x40; //如果在第2行 temp |= 0x80; LcdWriteCommand(temp,1); 1 2 3 4 5 6 } /******************************************* 函数名称:Disp1Char 功 能:在某个位置显示一个字符 参 数:x–位置的列坐标 y–位置的行坐标 data–显示的字符数据 返回值 :无 */ void Disp1Char(uchar x,uchar y,uchar data) { LocateXY( x, y ); LcdWriteData( data ); } / 函数名称:LcdReset 功 能:对1602液晶模块进行复位操作 参 数:无 返回值 :无 ********************************************/ void LcdReset(void) { CtrlDir |= 0x38; //控制线端口设为输出状态 DataDir = 0xFF; //数据端口设为输出状态 LcdWriteCommand(0x38, 0); //规定的复位操作 Delay5ms(); LcdWriteCommand(0x38, 0); Delay5ms(); LcdWriteCommand(0x38, 0); Delay5ms(); LcdWriteCommand(0x38, 1);//显示模式设置 LcdWriteCommand(0x08, 1);//显示关闭 LcdWriteCommand(0x01, 1); //显示清屏 LcdWriteCommand(0x06, 1);//写字符时整体不移动 LcdWriteCommand(0x0c, 1);//显示开,不开游标,不闪烁 1 2 3 4 5 6 7 8 9 10 11 12 } /******************************************* 函数名称:LcdWriteCommand 功 能:向液晶模块写入命令 参 数:cmd–命令, chk–是否判忙的标志,1:判忙,0:不判 返回值 :无 ********************************************/ void LcdWriteCommand(uchar cmd,uchar chk) { if (chk) WaitForEnable(); // 检测忙信号? CLR_RS; CLR_RW; _NOP(); DataPort = cmd; //将命令字写入数据端口 _NOP(); SET_EN; //产生使能脉冲信号 _NOP(); _NOP(); CLR_EN; 1 2 3 4 5 6 7 8 9 10 11 12 13 } /******************************************* 函数名称:LcdWriteData 功 能:向液晶显示的当前地址写入显示数据 参 数:data–显示字符数据 返回值 :无 ********************************************/ void LcdWriteData( uchar data ) { WaitForEnable(); //等待液晶不忙 SET_RS; CLR_RW; _NOP(); DataPort = data; //将显示数据写入数据端口 _NOP(); SET_EN; //产生使能脉冲信号 _NOP(); _NOP(); CLR_EN; 1 2 3 4 5 6 7 8 9 10 11 } /******************************************* 函数名称:WaitForEnable 功 能:等待1602液晶完成内部操作 参 数:无 返回值 :无 ********************************************/ void WaitForEnable(void) { P2DIR &= 0x00; //将P4口切换为输入状态 CLR_RS; SET_RW; _NOP(); SET_EN; _NOP(); _NOP(); while((P2IN & Busy)!=0); //检测忙标志 CLR_EN; P2DIR |= 0xFF; //将P4口切换为输出状态 1 2 3 4 5 6 7 8 9 10 11 12 } /******************************************* 函数名称:Delay5ms 功 能:延时约5ms 参 数:无 返回值 :无 */ void Delay5ms(void) { uint i=40000; while (i != 0) { i–; } } / 函数名称:Delay400ms 功 能:延时约400ms 参 数:无 返回值 :无 ********************************************/ void Delay400ms(void) { uchar i=50; uint j; while(i--) { j=7269; while(j--); } 1 2 3 4 5 } void DispNChar(unsigned char x,unsigned char y, unsigned char n,unsigned char *ptr); void LocateXY(unsigned char x,unsigned char y); void Disp1Char(unsigned char x,unsigned char y,unsigned char data); void LcdReset(void); void LcdWriteCommand(unsigned char cmd,unsigned char chk); void LcdWriteData( unsigned char data ); void WaitForEnable(void); void Delay5ms(void); void Delay400ms(void); #include <msp430x14x.h> typedef unsigned char uchar; typedef unsigned int uint; //unsigned char uchar; //unsigned int uint; /全局变量/ uchar key_Pressed; //按键是否被按下:1–是,0–否 uchar key_val; //存放键值 uchar key_Flag; //按键是否已放开:1–是,0–否 //设置键盘逻辑键值与程序计算键值的映射 uchar key_Map[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; /******************************************* 函数名称:Init_Keypad 功 能:初始化扫描键盘的IO端口 参 数:无 返回值 :无 / void Init_Keypad(void) { P1DIR = 0xf0; //P1.0~P1.3设置为输入状态, P1.4~P1.7设置为输出状态 P1OUT |= 0xf0; // P1.4~P1.7输出高电平 key_Flag = 0; key_Pressed = 0; key_val = 0; } /* Check_Key(),检查按键,确认键值 **/ / 函数名称:Check_Key 功 能:扫描键盘的IO端口,获得键值 参 数:无 返回值 :无 ********************************************/ void Check_Key(void) { uchar row ,col,tmp1,tmp2; tmp1 = 0x80; for(row = 0;row < 4;row++) //行扫描 { P1OUT = 0xf0; //P1.4~P1.7输出全1 P1OUT -= tmp1; //P1.4~p1.7输出四位中有一个为0 tmp1 >>=1; if ((P1IN & 0x0f) < 0x0f) //是否P1IN的P1.0~P1.3中有一位为0 { tmp2 = 0x01; // tmp2用于检测出那一位为0 for(col = 0;col < 4;col++) // 列检测 { if((P1IN & tmp2) == 0x00) // 是否是该列,等于0为是 { key_val = key_Map[row * 4 + col]; // 获取键值 return; // 退出循环 } tmp2 <<= 1; // tmp2右移1位 } } } } /******************************************* 函数名称:delay 功 能:延时约15ms,完成消抖功能 参 数:无 返回值 :无 ********************************************/ void delay() { uint tmp; for(tmp = 12000;tmp > 0;tmp–); } /******************************************* 函数名称:Key_Event 功 能:检测按键,并获取键值 参 数:无 返回值 :无 ********************************************/ void Key_Event(void) { uchar tmp; P1OUT &= 0x00; // 设置P1OUT全为0,等待按键输入 tmp = P1IN; // 获取 p1IN if ((key_Pressed == 0x00)&&((tmp & 0x0f) < 0x0f)) //如果有键按下 { key_Pressed = 1; // 如果有按键按下,设置key_Pressed标识 delay(); //消除抖动 Check_Key(); // 调用check_Key(),获取键值 } else if ((key_Pressed == 1)&&((tmp & 0x0f) == 0x0f)) //如果按键已经释放 { key_Pressed = 0; // 清除key_Pressed标识 key_Flag = 1; // 设置key_Flag标识 } else { _NOP(); } } 图片 ———————————————— 版权声明:本文为CSDN博主「科技论坛」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/zhangluan2019/article/details/109466230 |
| 发帖须知: 1,发帖请遵守《计算机信息网络国际联网安全保护管理办法》、《互联网信息服务管理办法》、 《互联网电子公告服务管理规定》、《维护互联网安全的决定》等法律法规。 2,请对您的言论负责,我们将保留您的上网记录和发帖信息。 3,在此发帖表示认同我们的条款,我们有权利对您的言论进行审核、删除或者采取其他在法律、地方法规等条款规定之内的管理操作。 |