小弟需要一个4*4键盘的按键服用的程序。
时间:10-02
整理:3721RD
点击:
小弟初学单片机,已经调通了单个按键的驱动,但是连续点击或者长按的程序始终没法搞定,还请大家多多帮助啊
用状态机思想能很容易实现你需要的功能,一般方式也可以实现但个人建议用状态机做,你先查些资料,试着自己实现它,对你更有利,遇到问题再交流
把4*4键盘的原理明白了,就很简单了,就是简单地扫描
扫描,有个美国的牛人,5个i/o口控制25个按键。
下载实例就会明白
终于搞定了这个,前后两天半时间啊。
- #include <msp430x14x.h>
- #define CPU_F ((double)8000000)
- #define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
- #define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
- #define uchar unsigned char
- #define uint unsigned int
- #define ulong unsigned long
- ;//*************************************************************************
- // 系统时钟初始化
- //*************************************************************************
- void Clock_Init()
- {
- uchar i;
- BCSCTL1&=~XT2OFF; //打开XT振荡器
- BCSCTL2|=SELM1+SELS; //MCLK为8MHZ,SMCLK为8MHZ
- do{
- IFG1&=~OFIFG; //清除震荡标志
- for(i=0;i<100;i++)
- _NOP(); //延时等待
- }
- while((IFG1&OFIFG)!=0); //如果标志为1,则继续循环等待
- IFG1&=~OFIFG;
- }
- //*************************************************************************
- // MSP430内部看门狗初始化
- //*************************************************************************
- void WDT_Init()
- {
- WDTCTL = WDTPW + WDTHOLD; //关闭看门狗
- }
- //*************************************************************************
- // 延时函数
- //*************************************************************************
- void delay(unsigned int m){
- for(unsigned int i=0;i<m;i++);
- }
- //*************************************************************************
- //串行通信传输函数 ,transdata为要写入的数据或指令
- //*************************************************************************
- void Lcd_InsWrite(uchar type,uchar transdata)
- {
- P5SEL=0X00;
- P5DIR=0XFF;
- P5OUT&=~BIT0;
- P5OUT|=BIT1;
- uchar firsttype=0xf8; //firsttype为第一字节,用来判断是写数据还是写指令。默认是写指令
- uchar temp;
- uchar i,j=3;
- //P1DIR=0xff;//P1口所有引脚设置为输出方向
- if(type) //判断是是写数据还是写指令,0为写指令,1为写数据
- firsttype=firsttype|0x02; //如果要写数据,则把第一字节的第二位至高
- P5OUT|=BIT5; //给CS高电平开始写入操作
- P5OUT&=~BIT7; //给SCLK时钟脉冲,在每个上升沿把数据写入到LCD
- while(j>0) //把写数据指令方式和要写入的数据发送给LCD
- {
- if(j==3) temp=firsttype; //确认要写入第一字节数据,及数据指令判断
- else if(j==2) temp=transdata&0xf0;//确认要写入第二字节数据
- else temp=(transdata<<4)&0xf0; //确认要写入第三字节数据
- for(i=8;i>0;i--) //把要写入的数据每个位由STD发送到LCD,写入
- {
- if(temp&0x80) P5OUT|=BIT6; //写入第一字节,及最高字节
- else P5OUT&=~BIT6;
- P5OUT|=BIT7; //给SCLK一个上升沿,写入一位
- temp<<=1; //把数据指令左移一位,开始写入下一位数据
- P5OUT&=~BIT7; //给SCLK一个低电平,确保下一次写入数据正常
- }
- delay(1); //做简单的延时
- j--; //准备写入下一字节数据
- }
- P5OUT&=~BIT5; //写入数据指令完毕,给STD和CS低电平
- P5OUT&=~BIT6;
- }
- //*************************************************************************
- // MSP430 LCD初始化
- //*************************************************************************
- void init_lcd(void)
- {
- Lcd_InsWrite(0,0x30); //基本指令
- delay(400);
- Lcd_InsWrite(0,0x04); //清除显示
- delay(400);
- Lcd_InsWrite(0,0x0c); //
- delay(400);
- Lcd_InsWrite(0,0x01);
- delay(400);// 显示状态设定:整体显示,游标on,游标位置反白
- Lcd_InsWrite(0,0x02);//DDRAM地址归位
- delay(400);
- }
- //********************************************************************
- // MSP430 读入键盘值
- //*************************************************************************
- char GetKey()
- {
- P1DIR |= 0XF0; //高四位输出
- for(int i=0;i<4;i++)
- {
- P1OUT = 0XEF << i;
- for(int j=0;j<4;j++)
- {
- if((P1IN&(0x01<<j))==0)
- {
- return (i+4*j);
- }
- }
- }
- return 0xff;
- }
- //*************************************************************************
- // 主函数
- //***********************************************************************void main(void)
- void main()
- {
- int i;
- char Data[30]="abcdefghijklmnopqrstuvwxyz,' .";
- int ID=0;
- WDT_Init(); //看门狗设置
- Clock_Init(); //系统时钟设置
- init_lcd();
- while(1) //无限循环
- {
- char temp1=GetKey();
- if(temp1==15){
- delay_ms(10);
- if(temp1==15){
- ID=0;
- delay_ms(200);
- }
- }
- if(temp1==14){
- if(Data[0]=='a'){
- for( int j=0;j<26;j++)
- Data[j]=Data[j]-32;
- }
- else{
- for(int j=0;j<26;j++)
- Data[j]=Data[j]+32;
- }
- }
- for(i=0;i<14;i++){
- if(temp1==i)
- {
- delay_ms(10);
- if(temp1==i)
- {
- ID++;
-
- if(ID==4){
-
- ID=1;
- }
- delay_ms(200);
- }
- switch(ID){
- case 1:
- Lcd_InsWrite(1,Data[3*i]);
- delay_ms(200);
- break;
-
- case 2:
- Lcd_InsWrite(1,' ');
- Lcd_InsWrite(0,0x10);
- delay_ms(200);
- Lcd_InsWrite(1,Data[3*i+1]);
- break;
-
- case 3:
- Lcd_InsWrite(1,' ');
- Lcd_InsWrite(0,0x10);
- Lcd_InsWrite(1,Data[3*i+2]);
- delay_ms(200);
- break;
- }
- }
- }
- }
- }
