MSP430 按键程序范例(附原理图)
MSP430触摸按键程序
//***************************************************************************** *// MSP430F20x3 Demo - Capacitive Touch Sensing 4-Key Demo// Description: This demo implements a 4-key capacitive touch detection.// The LED indicates the key which is pressed through four different levels of // brightness. Key#1 -> 100%, Key#2 -> 75%, Key#3 -> 50%, Key#4 -> 25%.// A calibration process is implemented to accommodate for possible variations // in VLO frequency. Normal operating mode is LPM3.//// ACLK = VLO ~ 12kHz, MCLK = Calibrated 8MHz / 4 = 2MHz,// SMCLK = Calibrated 8MHz//// MSP430F20x3// -----------------// /|\| XIN|-// | | |// --|RST XOUT|-// | |// | P1.0|---->LED// | | ####// | P1.2|----+--------#### Sensor#4// | | # ####// | | # R=5.1M// | | # ####// | P1.3|----+--------#### Sensor#3// | | ####// | |// | | ####// | P1.4|----+--------#### Sensor#2// | | # ####// | | # R=5.1M// | | # ####// | P1.5|----+--------#### Sensor#1// | | ####//// Zack Albus// Texas Instruments Inc.// June 2007// Built with IAR Embedded Workbench Version: 3.42A//***************************************************************************** *#include "msp430x20x3.h"// Define User Configuration values// Sensor settings#define Num_Sen 4 // Defines number of sensors#define S_4 (0x04) // Sensor 4 P1.2#define S_3 (0x08) // Sensor 3 P1.3#define S_2 (0x10) // Sensor 2 P1.4#define S_1 (0x20) // Sensor 1 P1.5#define LED (0x01) // P1.0#define min_KEY_lvl 30 // Defines the min key level threshold usable #define Sample_Rate 20 // Defines #/sec all sensors are sampled#define DCO_clks_per_sec 8000000 // Number of DCO clocks per second: 2MHz// Changes with DCO freq selected!#define DCO_clks_per_sample (DCO_clks_per_sec/Sample_Rate)/8// Clocks per sample cycle /8// /8 is allows integer usage// will be *8 in the final calcs#define LED_pulses_per_sample 5 // Defines LED pulses during each sample// -number of TACCR0 ints per sample#define Key_1_on_time 1 // Defines Key 4 % on#define Key_2_on_time 10 // Defines Key 3 % on#define Key_3_on_time 25 // Defines Key 2 % on#define Key_4_on_time 90 // Defines Key 1 % on// Global variables for sensingunsigned int dco_clks_per_vlo; // Variable used for VLO freq measurement unsigned int vlo_clks_per_sample; // Variable that determines vlo clocks per sample// vlo_clks_per_sample = DCO_clks_per_sample/dco_clks_per_vlo*8unsigned int vlo_clks_per_LED_pulse; // V ariable that determines vlo clocks per LED pulseunsigned int LED_on_time[Num_Sen]; // Stores calculated TACCR1 value for each// key separately. Calculated from//Key_x_on_time*vlo_clks_per_LED_pulse/100// Misc Globalsunsigned int base_cnt[Num_Sen];unsigned int meas_cnt[Num_Sen];int delta_cnt[Num_Sen];unsigned char key_press[Num_Sen];char key_pressed, key_loc, no_key, key_loc_old, key_time_out;char cycles;unsigned int timer_count;unsigned int KEY_lvl = 100; // Defines the min count for a "key press"// System Routinesvoid Init_Timings_Consts(void); // Use VLO freq to determine TA valuesvoid measure_count(void); // Measures each capacitive sensorextern unsigned int Measure_VLO_SW(void); // External function to measure// speed of the VLO// (implemented in Measure_VLO_SW.s43) // Main Functionvoid main(void){unsigned int i,j;int temp;// Configure clock systemWDTCTL = WDTPW + WDTHOLD; // Stop watchdog timerdco_clks_per_vlo = Measure_VLO_SW(); // Determine VLO freq for usageBCSCTL2 |= DIVM_2; // MCLK / 4BCSCTL1 = CALBC1_8MHZ; // Set DCO to 8MHzDCOCTL = CALDCO_8MHZ; // MCLK = 8/4 = 2MHzBCSCTL3 |= LFXT1S_2; // LFXT1 = VLO// Configure GPIOsP1OUT = 0x00; // P1.x = 0P1DIR = 0xFF; // P1.x = outputP2OUT = 0x00;P2DIR = 0xFF; // P2.x = outputP2SEL = 0x00; // No XTAL__enable_interrupt(); // Enable interruptsInit_Timings_Consts();measure_count(); // Establish an initial baseline capacitancefor (i = 0; i<Num_Sen; i++)base_cnt = meas_cnt;for (i=15; i>0; i--) // Repeat and average base measurement{measure_count();for (j = 0; j<Num_Sen; j++)base_cnt[j] = (meas_cnt[j]+base_cnt[j])/2;}no_key = 0;// Main loop starts herewhile (1){key_pressed = 0; // Assume no keys are pressedmeasure_count(); // Measure all sensorsfor (i = 0; i<Num_Sen; i++){delta_cnt = meas_cnt - base_cnt; // Calculate delta: c_change// Handle baseline measurment for a base C decreaseif (delta_cnt < 0) // If negative: result decreased{ // below baseline, i.e. cap decreased base_cnt = (base_cnt+meas_cnt) >> 1; // Re-average baseline down quicklydelta_cnt = 0; // Zero out delta for position determination }if (delta_cnt > KEY_lvl) // Determine if each key is pressed per a preset threshold {key_press = 1; // Specific key pressedkey_pressed = 1; // Any key pressedkey_loc = i;}elsekey_press = 0;}// Handle baseline measurement for a base C increaseif (!key_pressed) // Only adjust baseline up if no keys are touched {key_time_out = Sample_Rate*3; // Reset key time out durationfor (i = 0; i<Num_Sen; i++)base_cnt = base_cnt + 1; // Adjust baseline up, should be slow to} // accomodate for genuine changes in sensor C else // Key pressed{if (key_loc_old == key_loc) // same key pressed?key_time_out--;elsekey_time_out = Sample_Rate*3; // Reset key time out durationkey_loc_old = key_loc;if (key_time_out == 0) // After time-out, re-init base and key levelWDTCTL = WDTHOLD; // FORCE RESET}// Dynamically adjust key thresholdsif (key_pressed && (delta_cnt[key_loc]>>2 > KEY_lvl)){temp = delta_cnt[key_loc]>>2;temp = temp + KEY_lvl;temp = temp>>1;KEY_lvl = temp; // Average result}else if (!key_pressed){for (i = 0; i<Num_Sen; i++){if(delta_cnt > min_KEY_lvl){temp = delta_cnt>>1; // Means min key level threshold = %50 of delta measuredtemp = temp + KEY_lvl; // or = min_KEY_lvl/2temp = temp>>1;KEY_lvl = temp; // Average resultbreak;}}}if (key_pressed) // Pulse LED and use defined sample rate{no_key = Sample_Rate*3; // Reset ~3 sec delay until slower sample rate is usedcycles = LED_pulses_per_sample; // Re-set LED pulse counterTACCTL0 = CCIE;TACCR0 = vlo_clks_per_LED_pulse; // Load LED pulse periodTACCTL1 = CCIE;TACCR1 = LED_on_time[key_loc]; // Load LED pulse duty cycleP1OUT |= LED; // Turn on LED}else // No key is pressed...{if (no_key == 0) // ...~3 sec timeout expired: no key press in ~3secs...{cycles = 1; // Adjust cycles for only one TA delayTACCTL0 = CCIE;TACCR0 = vlo_clks_per_LED_pulse*LED_pulses_per_sample*5; // Low sample rate to: sample_rate/5 SPS}else // ... still within 3 secs of last detected key press...{no_key--; // Decrement delaycycles = LED_pulses_per_sample; // Maintain sample_rate SPS, without LEDTACCTL0 = CCIE;TACCR0 = vlo_clks_per_LED_pulse;}P1OUT ^= BIT6; // Toggle P1.6 (for debug only)}TACTL = TACLR + TASSEL_1 + MC_1; // ACLK = VLO, up modeLPM3;}} // End Main// Measure count result (capacitance) of each sensor// Routine setup for four sensors, not dependent on Num_Sen value!void measure_count(void){unsigned char i;char active_key;TACTL = TASSEL_2+MC_2; // SMCLK, cont modefor (i = 0; i<Num_Sen; i++){active_key = 1 << i+2; // define bit location of active key//***************************************************************************** *// Negative cycle//***************************************************************************** *P1OUT &=~(S_1+S_2+S_3+S_4); // everything is low// Take the active key high to charge the padP1OUT |= active_key;// Allow a short time for the hard pull high to really charge the pad__no_operation();__no_operation();__no_operation();// Enable interrupts (edge set to low going trigger)// set the active key to input (was output high), and start the// timed discharge of the pad.P1IES |= active_key; //-ve edge triggerP1IE |= active_key;P1DIR &= ~active_key;// Take a snaphot of the timer...timer_count = TAR;LPM0;// Return the key to the driven low state, to contribute to the "ground"// area around the next key to be scanned.P1IE &= ~active_key; // disable active key interruptP1OUT &= ~active_key; // switch active key to low to discharge the keyP1DIR |= active_key; // switch active key to output low to save powermeas_cnt= timer_count;//**************************************************************************** // Positive Cycle//**************************************************************************** P1OUT |= (S_1+S_2+S_3+S_4); // everything is high// Take the active key low to discharge the padP1OUT &= ~active_key;// Allow a short time for the hard pull low to really discharge the pad__no_operation();__no_operation();__no_operation();// Enable interrupts (edge set to high going trigger)// set the active key to input (was output low), and start the// timed discharge of the pad.P1IES &= ~active_key; //+ve edge triggerP1IE |= active_key;P1DIR &= ~active_key;// Take a snaphot of the timer...timer_count = TAR;LPM0;// Return the key to the driven low state, to contribute to the "ground"// area around the next key to be scanned.P1IE &= ~active_key; // disable active key interruptP1OUT &= ~active_key; // switch active key to low to discharge the keyP1DIR |= active_key; // switch active key to output low to save powerP1OUT &=~(S_1+S_2+S_3+S_4); // everything is lowmeas_cnt = (meas_cnt + timer_count) >> 1; // Average the 2 measurements}TACTL = TACLR; // Stop the timer}void Init_Timings_Consts(void){// dco_clks_per_vlo = dco_clks_per_vlo << 1; // x2 for 2MHz DCO// dco_clks_per_vlo = dco_clks_per_vlo << 2; // x4 for 4MHz DCOdco_clks_per_vlo = dco_clks_per_vlo << 3; // x8 for 8MHz DCO// dco_clks_per_vlo = dco_clks_per_vlo << 4; // x16 for 16MHz DCOvlo_clks_per_sample = DCO_clks_per_sample/dco_clks_per_vlo*8;vlo_clks_per_LED_pulse = vlo_clks_per_sample/LED_pulses_per_sample;LED_on_time[0] = Key_1_on_time*vlo_clks_per_LED_pulse/100;if(LED_on_time[0] == 0)LED_on_time[0] = 1;LED_on_time[1] = Key_2_on_time*vlo_clks_per_LED_pulse/100;LED_on_time[2] = Key_3_on_time*vlo_clks_per_LED_pulse/100;LED_on_time[3] = Key_4_on_time*vlo_clks_per_LED_pulse/100;}// Port 1 interrupt service routine#pragma vector=PORT1_VECTOR__interrupt void port_1_interrupt(void){P1IFG = 0; // clear flagtimer_count = TAR - timer_count; // find the charge/discharge timeLPM0_EXIT; // Exit LPM0 on reti}// Timer_A0 interrupt service routine#pragma vector=TIMERA0_VECTOR__interrupt void Timer_A0 (void){cycles--;if (cycles > 0){if (key_pressed)P1OUT |= LED; // LED on for TACCR1 time of TA period }else{ TACTL = TACLR;TACCTL0 = 0; // interrupt disabledTACCTL1 = 0; // interrupt disabledLPM3_EXIT; // Exit LPM3 on reti}}// Timer_A1 interrupt service routine#pragma vector=TIMERA1_VECTOR__interrupt void Timer_A1 (void){TACCTL1 &= ~CCIFG; // Clear the flagP1OUT &= ~LED; // LED off for rest of TA period }。
msp430Led按键控制灯亮程序
1.Led灯控制程序#include "msp430g2553.h"void main( void ){// Stop watchdog timer to prevent time out resetWDTCTL = WDTPW + WDTHOLD; //关闭看门狗//P1DIR = 0x41;//P1OUT = 0x41; //程序点亮led1//P1DIR |=BIT0+BIT6;//P1OUT |=BIT0+BIT6; //程序点亮led2P1DIR |=BIT0;P1OUT |=BIT0;P1DIR |=BIT6;P1OUT &=~BIT6;while(1){P1OUT ^=BIT0;P1OUT ^=BIT6;__delay_cycles(1000000);} //led交替亮,持续1s2.Led按键控制灯亮#include "msp430g2553.h"void main( void ){// Stop watchdog timer to prevent time out resetWDTCTL = WDTPW + WDTHOLD;//关闭看门狗P1DIR &=~BIT3;P1DIR |=BIT0;P1IES |=BIT3;P1IE |=BIT3;_EINT();_BIS_SR(LPM0_bits+GIE);}#pragma vector=PORT1_VECTOR__interrupt void PORT1_ISR(void){int i;char pushkey;pushkey=P1IFG&BIT3;//第三位中断标志位for(i=0;i<1000;i++)//短暂延时软件去抖if((P1IN&pushkey)==pushkey){P1IFG=0;//中断标志清零return;}if(P1IFG&BIT3)//判断按键是否按下{P1OUT^=BIT0;}P1IFG=0;return;}3.矩阵键盘和数码管程序#include <msp430g2553.h>#include"Key&Display.h"//unsigned char Receive(void);void main( void ){// Stop watchdog timer to prevent time out resetWDTCTL = WDTPW + WDTHOLD;Init_4lines_Mode();//初始化4线工作模式Send_Command(CH452_RESET);//CH452芯片内部复位Send_Command(KeyDisplay_ON);//允许显示驱动并启动键盘扫描//开中断,P2.0接CH452的DOUT引脚,当有键按下时,DOUT上产生由高到低的脉冲// P2SEL &= ~(BIT6+BIT7);P2IE|=BIT0;P2IES|=BIT0;P2IFG&=~BIT0;_EINT();while(1){}}//中断处理函数#pragma vector = PORT2_VECTOR//中断处理程序,接收到DOUT脉冲信号时,运行之__interrupt void Port2(void){unsigned char Keyvalue;Send_Command(CH452_GET_KEY);//单片机向CH452发送读取按键代码命令Keyvalue=Key_Read();// Keyvalue=Receive();switch(Keyvalue){case 0x40://按键K0按下{Send_Command( NDis1); //第1位数码管不显示//Send_Command(Dis10);Send_Command(Dis00);//第0位数码管显示0break;}case 0x41://按键K1按下{Send_Command( NDis1); //第1位数码管不显示//Send_Command(Dis10);Send_Command(Dis01);//第0位数码管显示1break;}case 0x42://按键K2按下{Send_Command( NDis1); //第1位数码管不显示//Send_Command(Dis10);Send_Command(Dis02);//第0位数码管显示2break;}case 0x43://按键K3按下{Send_Command( NDis1);//第1位数码管不显示//Send_Command(Dis10);Send_Command(Dis03);//第0位数码管显示3break;}case 0x48://按键K4按下{Send_Command( NDis1);//第1位数码管不显示//Send_Command(Dis10);Send_Command(Dis04);//第0位数码管显示4break;}case 0x49://按键K5按下{Send_Command( NDis1);//第1位数码管不显示//Send_Command(Dis10);Send_Command(Dis05);//第0位数码管显示5break;}case 0x4A://按键K6按下{Send_Command( NDis1);//第1位数码管不显示//Send_Command(Dis10);Send_Command(Dis06);//第0位数码管显示6break;}case 0x4B://按键K7按下{Send_Command( NDis1);//第1位数码管不显示//Send_Command(Dis10);Send_Command(Dis07);//第0位数码管显示7break;}case 0x50://按键K8按下{Send_Command( NDis1);//第1位数码管不显示//Send_Command(Dis10);Send_Command(Dis08);//第0位数码管显示8break;}case 0x51://按键K9按下{Send_Command( NDis1);//第1位数码管不显示//Send_Command(Dis10);Send_Command(Dis09);//第0位数码管显示9break;}case 0x52://按键K10按下{Send_Command(Dis00);//第0个数码管显示字符"0"Send_Command(Dis11);//第1个数码管显示字符"1"break;}case 0x53://按键K11按下{Send_Command(Dis01);//第0个数码管显示字符"1"Send_Command(Dis11);//第1个数码管显示字符"1"break;}case 0x58://按键K12按下{Send_Command(Dis02);//第0个数码管显示字符"2"Send_Command(Dis11);//第1个数码管显示字符"1"break;}case 0x59://按键K13按下{Send_Command(Dis03);//第0个数码管显示字符"3"Send_Command(Dis11);//第1个数码管显示字符"1"break;}case 0x5A://按键K14按下{Send_Command(Dis04);//第0个数码管显示字符"4"Send_Command(Dis11);//第1个数码管显示字符"1"break;}case 0x5B://按键K15按下{Send_Command(Dis05);//第0个数码管显示字符"5"Send_Command(Dis11);//第1个数码管显示字符"1"break;}default:break;}P2IFG&=~BIT0;}4.红灯0.2秒闪一次,绿灯0.8秒闪一次#include <msp430g2553.h>void main(void){WDTCTL = WDTPW + WDTHOLD; // Stop WDT BCSCTL1 &=~XTS; //配置时钟BCSCTL3 |=LFXT1S_2;IFG1 &=OFIFG;P1DIR |=BIT0+BIT6; // P1.0,P1.6 output P1OUT &=~BIT0; // P1.0,P1.6置0 P1OUT &=~BIT6;TACCR0 = 12000-1; //1秒定时,产生中断TACCR1 = 2400; //频率0.2*12000,定时0.2秒TACCR2 = 9600; //定时0.8秒TACTL = TASSEL_1 + MC_1+TAIE; // ACLK, 增计数模式TACCTL1 |=CCIE; // TACCR1中断使能TACCTL2 |=CCIE; // TACCR1中断使能_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt}// Timer_A3 Interrupt Vector (TA0IV) handler#pragma vector=TIMER0_A1_VECTOR__interrupt void Timer_A(void){switch( TA0IV ){case 2: P1OUT ^= BIT0; // 捕获/比较寄存器TACCR1break;case 4: P1OUT ^= BIT6;break; // 捕获/比较寄存器TACCR2case 10: break; // 未使用,计数达到TACCRO时执行中断,即1秒执行一次}}5.PMW波控制led灯亮度#include "msp430g2553.h"void main( void ){// Stop watchdog timer to prevent time out resetWDTCTL = WDTPW + WDTHOLD;P1DIR |=BIT6; //方向寄存器P1SEL |=BIT6; //功能寄存器TACTL=TASSEL_2+MC_1+ID_0; //定时器A控制寄存器选择增计数模式TACCTL1 |=OUTMOD_3; //捕获/比较控制寄存器TACCR0=1000-1;TACCR1=10;_BIS_SR(CPUOFF);}。
msp430全部基础程序集合
本文档由“X-TAB论坛”提供()1 [入门必修]按键检测与程序结构...菜菜//// MC430F224// -----------------// /|\| |// | | |// --|RST in1 |--~^~-------|GND KEY1 1// | in2 |--~^~-------|GND KEY2// | in3 |--~^~-------|GND KEY3// | |// | out1 |------|<|---|Vcc D1 LED// | out2 |------|<|---|Vcc D2 LED// | out3 |------|<|---|Vcc D3 LED////************************MC430F224*********************** *********************#includ e <msp430x22x4.h>//初级用户要习惯采用宏定义,以方便的编写和修改#define keyio 0xf1 //定义按键IO口,所有键口为0.#define key_1 0xfd //定义返回键值1#define key_2 0xfb //定义返回键值2#define key_3 0xf7 //定义返回键值3#define LED_D1_flas h P1OUT^= BIT1#define LED_D2_flas h P1OUT^= BIT2#define LED_D3_flas h P1OUT^= BIT3#define bell_d elay7000//声明子程序unsign ed char key_ch cek(void);void displa y_upd ate(unsign ed char dta);void key_pr ocess_0(void);void key_pr ocess_1(void);void key_pr ocess_2(void);//********************************************************** ***************//将单片机初始化程序放在m ain()前面是方便查看单片机的初始化状态情况.void MCU_in t(void){//默认MCLK主时钟频率为DCO=~800KP1OUT|= BIT1+BIT2+BIT3; //设置LED,上电为灭.电路可以查看M C430F14电路图.P1DIR|= BIT1+BIT2+BIT3; //P1.1设置为输出.//MSP430单片机IO口上电默认方向为输入,所以接按键的I O无需再设为输入.}//********************************************************** ***************void main (void){ unsign ed char key_va lue; //定义键值全局变是WDTCTL = WDTPW + WDTHOL D;//关狗MCU_in t(); //初始化单片机while(1) //主程序主循环{key_va lue=key_ch cek(); //检测,有键按下并松开,返回一个键值.switch(key_va lue) //对键值进行处理.采switc h 语法结构查询{case key_1: key_pr ocess_0(); //调用键处理程序1b reak;case key_2: key_pr ocess_1(); //调用键处理程序2b reak;case key_3: key_pr ocess_2(); //调用键处理程序2b reak;defaul t: ; //调用键处理程序4b reak;}displa y_upd ate(key_va lue); //如果有需要可以在这里加上显示更新程序.key_value=0x00; //最后清除键值.将继续主循环.}}//********************************************************** ***************//按键检测程序//返回值: 无符号字符型键值unsign ed char key_ch cek(void){unsign ed int i;unsign ed char timp,active;active=0;while(!active){while(0xff ==( P2IN | keyio)); //一直等待有键按下timp = P2IN | keyio;//若有键接下了,则读入IO状态.for(i=0;i<7000;i++); //延时,是为了去按键抖动.if (timp ==(P2IN | keyio))//经延时后,还是那键吗?{ active = 1; //是,则按键有效.while(0xff !=( P2IN | keyio)); //一直等待按键松开}else{ //去按键抖动后读入的键值与之前不同.则先效.active = 0; //再循环检测.}}return timp; //返回一个键值.}//********************************************************** ***************void key_pr ocess_0(void) //值处理,用户可以自己修改... {LED_D1_flas h;}//********************************************************** ***************void key_pr ocess_1(void) //值处理,用户可以自己修改... {LED_D2_flas h;}//********************************************************** ***************void key_pr ocess_2(void) //值处理,用户可以自己修改... {LED_D3_flas h;}//********************************************************** ***************void displa y_upd ate(unsign ed char dta){; //用户可以根据需要来放置显示程序,如LCD,LED,Digita l-LED....//灵活应用,}//********************************************************** ***************2 [入门必修]串行异步通讯例子..菜菜微控网原创复制代码//********************************************************** ******************//描述:在微控MC430F224开发板上实现UAR T模块串行异步通讯实验。
MSP430 键盘程序
/*MSP430F42X系列单片机16位ADC通用程序库说明:该驱动程序库包含了常用的16位ADC操作与控制功能函数,如选择通道、设置信号放大/*带有缓冲区及长短键的键盘通用程序库说明:该程序库包含了读取键盘的相关函数,并且包含了一个键盘缓冲区,当主程序执行较慢,而遇到连续快速的键盘输入来不及及时读取的情况下,新的按键信息将会自动存入键盘缓冲队列内,每次调用读键盘函数时会依顺序读取,保证键盘操作不会丢失。
并且带有长短按键识别功能,当按键时间小于2秒时,返回短键,按键超过2秒后,每隔0.25秒返回一次长按键。
该键盘程序可以作为各种程序的底层驱动使用。
要使用该库函数,需要将本文件(Key.c)添加进工程,并在需要调用键盘函数的文件开头处包含"Key.h";还需要开启一个定时器,在定时中断内调用Key_ScanIO()函数。
设置定时中断的频率在16~128次/秒之间。
*///+-------------+//|定时中断|软件结构//+-------------+//|//+-------------++-------------++-------------+// KEY1_IN -->| Key_ScanIO||KeyBuff[]||Key_GetKey() |// KEY2_IN -->|键盘扫描|-->|键盘缓冲|-->|Key_WaitKey()|-->应用程序// KEY3_IN -->|函数||队列(FIFO) ||键盘读取函数|//+-------------++-------------++-------------+//////MSP430F4XX//+---------------+//+---KEY1--|P1.5|//||XOUT|-----//+---KEY2--|P1.6|32.768KHz Watch Crystal//||XIN|-----//+---KEY3--|P1.7|//|+---------------+//GND//#include<msp430x42x0.h>#define KEYBUFF_SIZE8/*键盘缓冲区大小,根据程序需要自行调整*/ char KeyBuff[KEYBUFF_SIZE]; //定义键盘缓冲队列数组(FIFO)char Key_IndexW=0;//键盘缓冲队列写入指针(头指针)char Key_IndexR=0;//键盘缓冲队列读取指针(尾指针char Key_Count=0;//键盘缓冲队列内记录的按键次数char KEY1_State=0;char KEY2_State=0;char KEY3_State=0;/*3个按键的状态变量*/#define NOKEY0#define PUSH_KEY1#define LONG_PUSH 2#define KEY1_IN (P5IN&BIT5) //KEY1输入IO的定义(P6.4)#define KEY2_IN (P5IN&BIT6) //KEY2输入IO的定义(P6.5)#define KEY3_IN (P5IN&BIT7) //KEY3输入IO的定义(P6.6)#define KEY1 0x01//SET按键#define KEY2 0x02//增加按键#define KEY3 0x04//减小按键#define LONG0x80/*连续长键标志位宏定义*/#define FIRSTLONG 0xC0/*首次长键标志位宏定义*//***************************************************************** ************名称:Key_InBuff()*功能:将一次键值压入键盘缓冲队列*入口参数:Key:被压入缓冲队列的键值*出口参数:无********************************************************************* *******/void Key_InBuff(char Key){if(Key_Count>=KEYBUFF_SIZE) return;//若缓冲区已满,放弃本次按键_DINT();Key_Count++;//按键次数计数增加KeyBuff[Key_IndexW] = Key;//从队列头部追加新的数据if (++Key_IndexW >=KEYBUFF_SIZE) //循环队列,如果队列头指针越界{Key_IndexW = 0;//队列头指针回到数组起始位置}_EINT();}/*********************************************************** ******************名称:Key_GetKey()*功能:从键盘缓冲队列内读取一次键值*入口参数:无*出口参数:若无按键,返回0,否则返回一次按键键值。
MSP430程序HD7279键盘程序
//HD7279键盘程序#include "msp430g2452.h"#include "HD7279.h"static void delay_us(uint16 n) //N us延时函数{for(; n>0; n--);}void HD7279_Init(void){//HD7279_DIR |= HD7279_CS + HD7279_CLK + HD7279_DATA;HD7279_DIR |= HD7279_CLK + HD7279_DATA;HD7279_DIR &= ~HD7279_KEY;HD7279_IES |= HD7279_KEY; // 下降沿触发方式HD7279_IFG &= ~HD7279_KEY; // 清空中断标志HD7279_IE |= HD7279_KEY; // 使能KEY 中断//SendByte(0xA4); //清除缓存指令}/***发送一个字节的数据***/void SendByte(uint8 byte){uint8 i;HD7279_DIR |= HD7279_DA TA;HD7279_CLK_0;//HD7279_CS_0;delay_us(40);for (i=0;i<8;i++){if (byte&0x80)HD7279_DA TA_1;elseHD7279_DA TA_0;delay_us(1);HD7279_CLK_1;delay_us(12);HD7279_CLK_0;delay_us(12);byte = byte<<1;}HD7279_DATA_0;//HD7279_CS_1;}/***接收一个字节的数据***/uint8 ReceiveByte(void){uint8 i, state, out_byte;HD7279_CLK_0;HD7279_DIR &= ~HD7279_DATA;//HD7279_CS_0;delay_us(40);for (i=0;i<8;i++){HD7279_CLK_1;delay_us(12);out_byte=out_byte<<1;state = HD7279_IN & HD7279_DA TA;if (state == HD7279_DATA){out_byte=out_byte|0x01;}HD7279_CLK_0;delay_us(12);}//HD7279_CS_1;return (out_byte);}//写带数据的指令void write_7279(uint8 cmd, uint8 dat){SendByte(cmd);SendByte(dat);}uint8 read_7279(void){SendByte(0x15); // 发送读命令return (ReceiveByte());}/*void HD7279_disp(unsigned int disp_data){unsigned char shiwan,wan,qian,bai,shi,ge;unsigned int temp;temp = disp_data;shiwan = temp/100000;wan = temp%100000/10000;qian = temp%100000%10000/1000;bai = temp%100000%10000%1000/100;shi = temp%100000%10000%1000%100/10;ge = temp%100000%10000%1000%100%10;write_7279(0x80,ge);write_7279(0x81,shi);write_7279(0x82,bai);write_7279(0x83,qian);write_7279(0x84,wan);write_7279(0x85,shiwan);}*/uint8 Get_7279_KeyData(void){uint8 key_data, key_value;key_data = read_7279();if ((key_data < 8) && (key_data > 3))key_value = 8 - key_data;else if ((key_data < 16) && (key_data > 11))key_value = 20 - key_data;else if ((key_data < 24) && (key_data > 19))key_value = 32 - key_data;else if ((key_data < 32) && (key_data > 27))key_value = 44 - key_data;elsekey_value = 0;return (key_value);}//12864程序#include "msp430g2452.h"#include "12864.h"static void delay(uint16 t){unsigned int i,j;for(i=0; i<t; i++)for(j=0; j<14; j++);}void sendbyte(uint8 zdata){uint8 i;for(i=0; i<8; i++){if((zdata << i) & 0x80)SID_1;elseSID_0;SCLK_0;SCLK_1;}}void write_com(uint8 cmdcode){//CS_1;sendbyte(0xf8);sendbyte(cmdcode & 0xf0);sendbyte((cmdcode << 4) & 0xf0);delay(2);}void write_data(uint8 Dispdata){//CS_1;sendbyte(0xfa);sendbyte(Dispdata & 0xf0);sendbyte((Dispdata << 4) & 0xf0);delay(2);}void LCD_Init(void){LCD_DIR |= (LCD_SID + LCD_SCK);delay(2000);write_com(0x30);delay(50);write_com(0x0c);delay(50);write_com(0x01);//清屏delay(50);write_com(0x06);//00000110); //光标右移//06 delay(100);}void LCD_SetPosition(uint8 x,uint8 y){uint8 pos;if(x == 0)x = 0x80;else if(x == 1)x = 0x90;else if(x == 2)x = 0x88;else if(x == 3)x = 0x98;pos = x + y;write_com(pos);//显示地址}void LCD_DisplayString(uint8 *s){while(*s > 0){write_data(*s);s++;delay(50);}}void LCD_DisplayNumber(uint32 num, uint8 len){uint8 wei[10];uint8 i;uint8 flag = 0;for (i = 0; i < len; i++){wei[i] = num%10;num = num/10;}for (i = len; i > 0; i--){if ((wei[i-1] == 0) && (flag == 0) && (i > 1))write_data(' ');else if(wei[i-1] != 0)flag = 1;if (flag)write_data(wei[i-1]+0x30);}if (flag == 0)write_data('0');}void LCD_DisplayXiaoshu(uint32 num, uint8 len) {uint8 wei[10];uint8 i;for (i = 0; i < len; i++){wei[i] = num%10;num = num/10;}write_data('.');for (i = len; i > 0; i--){write_data(wei[i-1]+0x30);}}。
MSP430中断小实验——通过按键改变小灯闪烁频率
MSP430中断⼩实验——通过按键改变⼩灯闪烁频率本⼩实验基于MSP430f5529,不同的型号可能管脚和中断配置有所不同。
实现的功能为:第⼀次按下按键后,系统以每 2 秒钟,指⽰灯暗 1 秒,亮 1 秒的⽅式闪烁。
程序采⽤默认时钟配置;第⼆次按下按键后,系统以每 4 秒钟,指⽰灯亮 2 秒,暗 2 秒钟⽅式闪烁。
第三次按下按键后,系统以每 4 秒钟,指⽰灯亮 1 秒,暗 3 秒⽅式闪烁。
程序基于定时器配置。
/** main.c* 第⼀次按下按键后,系统以每 2 秒钟,指⽰灯暗 1 秒,亮 1 秒的⽅式闪烁,程序采⽤默认时钟配置;第⼆次按下按键后,系统以每 4 秒钟,指⽰灯亮 2 秒,暗 2 秒钟⽅式闪烁。
第三次按下按键后,系统以每 4 秒钟,指⽰灯亮 1 秒,暗 3 秒⽅式闪烁,程序基于定时器配置。
*/#include <msp430f5529.h>int count = 0; //计数int t1_50ms = 20; //⼀个单位对应50ms(亮)int t2_50ms = 20; //⼀个单位对应50ms(灭)int flag = 0; //闪烁频率标志int flag_t = 1; //亮灭标志int main(void) {WDTCTL = WDTPW+WDTHOLD;//时钟中断配置P1DIR |= BIT0;TA0CCTL0 = CCIE;//使能定时器中断TA0CCR0 = 50000;TA0CTL = TASSEL_2 + MC_1 + TACLR;//配置为SMCLK,升计数模式,初始化时钟//S1配置P1IE |= BIT7; //允许P1.7中断P1IES |= BIT7; //设置为下降沿中断P1IFG &= ~BIT7; //设置为输⼊P1REN |= BIT7; //启⽤上下拉电阻P1OUT |= BIT7; //将电阻设置为上拉__bis_SR_register(LPM0_bits+GIE); //打开中断return 0;}#pragma vector=TIMER0_A0_VECTOR__interrupt void TIMER0_A0_ISR(void){if(count==t1_50ms&&flag_t==1) //灯亮{P1OUT |= BIT0;count=0;flag_t=0;}else if(count==t2_50ms&&flag_t==0) //灯灭{P1OUT &=~BIT0;count = 0;flag_t=1;}else count++;}#pragma vector=PORT1_VECTOR;__interrupt void botton (void){__delay_cycles(75);//延时消抖switch(flag)//flag决定闪烁频率{case 0:t1_50ms = 20;t2_50ms = 20;break;//1秒亮 1秒暗case 1:t1_50ms = 40;t2_50ms = 40;break;//2秒亮 2秒暗case 2:t1_50ms = 60;t2_50ms = 20;break;//3秒亮 3秒暗}flag++;//状态变化if(flag>2) flag = 0;//flag归位P1IFG &=~ BIT7; //清除中断标志位__bis_SR_register(LPM0_bits+GIE);//打开中断}。
MSP430F149的定时器A操作
MSP430F149的定时器A定时操作1)定时器A的图解图1 定时器A图解2)定时器A的四种计数模式。
1.停止模式。
2.增计数模式。
(产生两个中断标志)也就是当计数到跟TACCR0一样的时候,就返回0,重新计数。
当计数到TACCR0的同时产生一个中断标志CCIFG,而当计数器溢出返回零的同时又同时产生一个中断标志TAIFG。
如图:图2 增计数模式的波形图3.连续计数模式。
(产生一个中断标志)也就是计数器将直接计数到计数器所能计数的最大值0FFFFH之后重新返回零,再次计数。
返回零的同时产生一个TAIFG中断标志。
如图:4.增减计数模式。
(产生两个中断标志)也就是当计数器计数到跟TACCR0一样的之后,然后从TACCR0开始又减少,直到为零,然后又开始增。
当计数跟TACCT0一样的时候产生一个中断标志CCIFG,当减到为零的时候又产生一个中断标志TAIFG。
如图:注意:当重新写入TACCR0数值的时候,当新的数据大于原来的数值的时候,计数器将计数到新的数值才重新返回零;当新的数据小于原来的数值的时候,计数器将直接返回零重新计数。
3)定时器A的寄存器。
1.TACTL●TASSELx:计时器A的时钟来源选择。
●IDx:计时器A时钟的分频选择。
●MCx:计时器A四种计数模式选择。
●TACLR:计数器A的TAR计数清零,同时也可以清楚时钟分频器和计数方向。
●TAIE:TAIFG中断标志使能。
在捕获模式下可以打开所有CCIFG的中断使能。
●TAIFG:中断标志位。
2.TAR计数器的计数寄存器。
3.TACCTLx●CMx:捕获模式选择。
00:关闭;01:上升沿捕获;10:下降沿捕获;11:上升下降沿捕获。
●CCISx:捕获引脚选择。
●SCS:选择捕获电平方式。
0异步时钟;1同步时钟。
●SCCI:锁存同步时钟输入端。
也就是锁存EQUx的值,以供CPU读取。
●CAP:捕获模式和比较模式选择。
0比较;1捕获。
●OUTMODx:输出模式选择。
MSP430按键程序范例(附原理图)
MSP430按键程序范例(附原理图)#i ncludevoid Init_Port(void){//将P1口所有的管脚在初始化的时候设置为输入方式 P1DIR = 0; //将P1口所有的管脚设置为一般I/O口P1SEL = 0;// 将P1.4 P1.5 P1.6 P1.7设置为输出方向P1DIR |= BIT4;P1DIR |= BIT5;P1DIR |= BIT6;P1DIR |= BIT7;//先输出低电平P1OUT = 0x00;// 将中断寄存器清零P1IE = 0;P1IES = 0;P1IFG = 0;//打开管脚的中断功能//对应的管脚由高到低电平跳变使相应的标志置位P1IE |= BIT0;P1IES |= BIT0;P1IE |= BIT1;P1IES |= BIT1;P1IE |= BIT2;P1IES |= BIT2;P1IE |= BIT3;P1IES |= BIT3;_EINT();//打开中断return;}void Delay(void){int i;for(i = 100;i--;i > 0) ;//延时一点时间}int KeyProcess(void){int nP10,nP11,nP12,nP13;int nRes = 0;//P1.4输出低电平P1OUT &= ~(BIT4);nP10 = P1IN & BIT0;if (nP10 == 0) nRes = 13; nP11 = P1IN & BIT1; if (nP11 == 0) nRes = 14; nP12 = P1IN & BIT2; if (nP12 == 0) nRes = 15; nP13 = P1IN & BIT3; if (nP13 == 0) nRes = 16; //P1.5输出低电平P1OUT &= ~(BIT4);nP10 = P1IN & BIT0;if (nP10 == 0) nRes = 9; nP11 = P1IN & BIT1; if (nP11 == 0) nRes = 10; nP12 = P1IN & BIT2; if (nP12 == 0) nRes = 11; nP13 = P1IN & BIT3; if (nP13 == 0) nRes = 12; //P1.6输出低电平P1OUT &= ~(BIT4);nP10 = P1IN & BIT0;if (nP10 == 0) nRes = 5; nP11 = P1IN & BIT1; if (nP11 == 0) nRes = 6; nP12 = P1IN & BIT2; if (nP12 == 0) nRes = 7; nP13 = P1IN & BIT3; if (nP13 == 0) nRes = 8; //P1.7输出低电平P1OUT &= ~(BIT4);nP10 = P1IN & BIT0;if (nP10 == 0) nRes = 1; nP11 = P1IN & BIT1;if (nP11 == 0) nRes = 2; nP12 = P1IN & BIT2;if (nP12 == 0) nRes = 3; nP13 = P1IN & BIT3;if (nP13 == 0) nRes = 4; P1OUT = 0x00;//恢复以前值。
MSP430单片机 矩阵键盘与数码管实验(附原理图)
MSP430单片机矩阵键盘与数码管实验(附原理图)/************************************************************* *MSP430单片机矩阵键盘与数码管实验*功能:用共阳极数码管显示按键的键值*适用:MSP430各系列单片机*by:duyunfu1987*************************************************************/ #include "msp430x44x.h"#define ROW P2OUT //矩阵键盘的行宏定义#define COL P2IN //矩阵键盘的列宏定义#define DPYOUT P3OUT //数码管输出口宏定义unsigned char keyval; //键值//共“阳”极数码管的码表unsigned char LED7CA[] ={~0x3F,~0x06,~0x5B,~0x4F,~0x66,~0x6D,~0x7D, ~0x07,~0x7F,~0x6F,~0x77,~0x7C,~0x39,~0x5E,~0x79,~0x71,0xff};/********************************************************函数名称:keyscan()*功能:扫描4*3矩阵键盘,并返回键值*出口参数:若有按键则返回键值,若无按键返回15*4*3矩阵键盘:0 1 2 3* 4 5 6 7* 8 9 A b*******************************************************/ unsigned char keyscan(){int i=0;unsigned char key=0;ROW = 0x8f; //先置三行输出低电平if((COL & 0x0f)!= 0x0f) //是否有按键{do i++;while(i<3000); //消抖动延时ROW = 0xbf; //扫描第一行if((COL & 0x0f)== 0x0f){ ROW = 0xdf; //扫描第二行if((COL & 0x0f)== 0x0f){ ROW = 0xef; //扫描第三行if((COL & 0x0f)== 0x0f)key = 15;else key = ~((ROW & 0XF0)|(COL & 0X0F));}else key = ~((ROW & 0XF0)|(COL & 0X0F));}else key = ~((ROW & 0XF0)|(COL & 0X0F));if(key != 15)switch(key) //获取有效地键值{ case 0x48: key=0; break;case 0x44: key=1; break;case 0x42: key=2; break;case 0x41: key=3; break;case 0x28: key=4; break;case 0x24: key=5; break;case 0x22: key=6; break;case 0x21: key=7; break;case 0x18: key=8; break;case 0x14: key=9; break;case 0x12: key=10;break;case 0x11: key=11;break;default: key=15;}}else key = 15;keyval=key;return key;}void main( void ){// Stop watchdog timer to prevent time out resetWDTCTL = WDTPW + WDTHOLD;P3DIR |= 0xff;P3OUT = 0xff; //共阳极数码管输出口初始化P2DIR |= BIT4 +BIT5+BIT6; //先配置矩阵键盘的行(输出)//P2.6 第一行,P2.5 第二行,P2.4 第三行//P2.3 第一列,P2.2 第二列,P2.1 第三列,P2.0 第四列keyval=16;while(1){ keyscan();if(keyval != 15 && keyval<17)DPYOUT = LED7CA[keyval];//数码管显示键值}}。
msp430按键控制LED最基本程序
msp430按键控制LED最基本程序按键篇经过一短时间的学习,下面,亲自动手编写一下程序吧。
程序的目的是:按下按键,控制LED的亮和灭。
短按键,则小灯亮1秒,然后灭; 长按键,小灯常亮。
首先,完成键盘的扫描程序。
第一点:如果是扫描,就要用到定时器。
我想设计定时器每隔IOms扫描一次按键。
定时器,我选用定时器A。
它的定时中断函数如下:函数名称:TimerA_ISR功能:定时器A 的中断服务函数参数:无返回值:无********************************************/ #pragma vector = TIMERAO_VECTOR __interrupt void TimerA_ISR(void) {GetKey() ;}上面这个定时中断函数的意思就是:每当定时时间到了以后,就调用GetKey() 函数一次。
GetKey() 函数就是扫描键盘按键的函数了。
在GetKey() 函数中,会根据按键类型(长按/ 短按)返回不同的数值。
根据返回的数值,做小灯亮法的操作。
那么,返回的这个值,我们需要保存在一个变量中,在这里定义一个变量ucharFlagLcd ; 来保存返回值。
这个变量在全局变量中定义,以保证它的作用域。
那么定时函数就变为#pragma vector = TIMERAO_VECTOR__interrupt void TimerA_ISR(void){FlagLcd =GetKey() ;}定时器中断的时间间隔,我在主函数中定义。
这样写:CCTLO = CCIE; // 使能CCR冲断CCRO = 4O; // 设定周期O.O1STACTL = TASSEL_1 + ID_3 + MC_1; //定时器A的时钟源选择ACLK增计数模式这样,定时器这块就算完工了。
那么,下面进行按键扫描程序。
按键的定义是这样的,根据我板子的按键原理图如下Pl +PlAPl 了这是一个矩阵键盘。
MSP430开发板原理图
64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 P5.4/MCLK P5.3/UCLK1 P5.2/SOMI1 P5.1/SIMO1 P5.0/STE1 P4.7/TBCLK P4.6/TB6 P4.5/TB5 P4.4/TB4 P4.3/TB3 P4.2/TB2 P4.1/TB1 P4.0/TB0 P3.7/URXD1 P3.6/UTXD1 P3.5/URXD0
J4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 SIP16-2.54 P5.5 P5.6 P5.7 XT2OUT XT2IN TDO TDI TMS TCK RST P6.0 P6.1 P6.2 AVSS GND 3.3V
MSP430F169IPM
B
Q9 8550
P1 + D2 D1 USB S10 C4 10UF/16V
IN
GND
f g dp d dp dp dp d d
4×4矩阵键盘
a b c d e f g b f g b f g b f g b a a
e d c b a
dp g f
e c e c e c e
e d
f g b f g b f g b f g b a
dp dp
c e d c e d c e d c
J3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 SIP16-2.54 P3.5 P3.6 P3.7 P4.0 P4.1 P4.2 P4.3 P4.4 P4.5 P4.6 P4.7 P5.0 P5.1 P5.2 P5.3 P5.4
R28 5.1K P1.3 K3 SW-PB K7 SW-PB K11 SW-PB K15 SW-PB
MSP430F149开发板电路原理图
U9 DAC0832
CS W R1 AGND D3 D2 D1 D0 Vref Rfb DGND
VCC IL E W R2 XFE R D4 D5 D6 D7 Iout2 Iout1
20
VCC
19
18 DAC_W R
17 DAC_CS
16 DAC_D4
15 DAC_D5
14 DAC_D6
13 DAC_D7
JP9 HE ADER 8X2
P1 .0
P1 0
P1 .1
1
2
P1 1
P1 .2
3
4
P1 2
P1 .3
5
6
P1 3
P1 .4
7
8
P1 4
P1 .5
9
10
P1 5
P1 .6
11
12
P1 6
P1 .7
13
14
P1 7
15
16
X2
C1
30p f
Y1
11. 0592M
C2
30p f
X1
J4
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
4 5 6 15 16 17
D/I R/W E CS1 CS2 RST
LC M_D 0 LC M_D 1 LC M_D 2 LC M_D 3 LC M_D 4 LC M_D 5 LC M_D 6 LC M_D 7
7 8 9 10 11 12 13 14
D0 D1 D2 D3 D4 D5 D6 D7
LC D1286 4
LED LED LED LED LED LED LED LED
MSP430矩阵键盘程序源码
// 上一次按键值刷新
}
if (K_STOP_HV&key) key = K_STOP_HV;
} //***************************************************************************
//*************************************************************************** //***************************************************************************
shift<<=1;
}
//--------------------------------------------------------------------------
if (code_now == key_last)
{
if (++key_delay >= T_delay)
// 同一按键按住是否超过预定时间
{
key_delay = T_delay - T_dlyup; // 设置新值以使按键快输反应,
f_key = 1;
// 设置标志
f_key_all=1;
}
}
else
// 有新键按下
{
f_key = 1;
// 设置标志
key_delay = 0;
// 计数器复位
key = key_last = code_now;
#define BASE_T0 10
// T0 基本定时周期为 20ms,用于键盘定时扫描
#define T_dlyup (100/BASE_T0)
MSP430程序库七按键
MSP430程序库七按键msp430程序库按键键是单片机系统中最常用的输入设备之一;几乎只要需要交互式输入,就必须有键盘。
这个博客实现了一个通用键盘程序。
只要它提供一个读取键值(底部键值)的函数,程序就会完成一些列处理,比如去抖振、存储在队列中等等。
同时,本程序提供了最常用的4*4矩阵键盘程序和4键程序。
硬件介绍:本文主要实现了一个键盘的通用框架,可以很方便的改为不同的键盘函数,这里实现了两种按键4个单独按键和4*4行列扫描的键盘。
四个按键的工作原理如下:四个按键的一端接地,另一端连接上拉电阻,然后输入单片机0-P1的P1。
3个港口;这样,当按键时,单片机接收到一个低电平。
释放时,单片机输入信号具有上拉电阻,并固定在高电平。
4*4的按键:行输入信号配有桑拉电阻,无按键时默认电平高电平;列扫描信号线直接接到按键列线;读键时,列扫描信号由单片机给出低电平信号(按列逐列扫描),读取行信号,从而判断具体是哪个按键;电路图大概如下:在图中,In是键盘的列扫描线,out是键盘输出的行信号线。
扫描也可以按行扫描。
此时,in是行扫描行,out是键输出的列信号行。
我的程序按列扫描(行和列扫描的原理相同,但行和列是交换的)。
这里,同时实现了4*4按键的scanf函数的移植,同时,加入了之前实现的液晶的printf函数的移植,搭建了一个可以交互输入输出的完整的一个系统;液晶的printf又加入了函数,实现了退格;可以在输入错误数字的时候退格重新输入。
程序实现:首先,我们来谈谈这个项目的结构。
该程序实现了一个循环队列来存储按下的键值。
可以保存最新的四把钥匙,防止钥匙丢失;程序使用中断模式按键。
每16毫秒读取一次按键(使用看门狗的间隔中断),以判断按键值是否有效。
如果有效,将其放入队列并等待读取。
循环队列的实现:通过数组实现。
为了判断队列是否已满,数组的最后一个元素不需要存储密钥代码值:/**********************宏定义***********************/#definekeysize4//键码值队列#definelengthkeysize+1//队列数组元素个数/***************************************************//**********************键值队列*********************///可keysize(length-1)个键码循环队列占用一个元素空间charkey[length];入队函数:入队时,队满则出队一个,以保存最新的四个按键。
MSP430矩阵键盘程序
/***************************************************************** ***********keyboard for MSP430Designed by CUGer——Mr.Wei程序可用,当系统时钟改变时,注意修改按键消抖延时***************************************************************** ***********/#include<msp430x16x.h>#define KEY_DIR P1DIR#define KEY_OUT P1OUT#define KEY_INP1IN#define KEY_IEP1IE#define KEY_IES P1IES#define KEY_IFG P1IFG/***************全局变量***************/unsigned char Key_Val;void CtrlKey(unsigned char sw);/*******************************************函数名称:Init_Keypad功能:初始化扫描键盘的IO端口参数:无返回值:无********************************************/void Init_Keypad(void){KEY_DIR=0x0f;态,P1.4~P1.7输入状态(上拉H)KEY_OUT&=0xf0;(卫编)KEY_IES =0xf0;KEY_IE=0xf0;KEY_IFG= 0;Key_Val=16;值均可}/******************************************* 函数名称:Check_Key功能:扫描键盘的IO端口,获得键值参数:无//存放键值//控制键盘开关//sw=0关sw=1开//P1.0~P1.3设置为输出状//P1.0~P1.3输出为低电平//P1.4~P1.7下降沿触发中断//P1.4~P1.7允许中断//中断标志清0//按键值初始设为非0~15的返回值:无********************************************/ //p14\5\6\7接上拉电阻/***************************************key_Val对应键值列:[p14][p15][p16][p17]↓↓↓↓行:[p13]→0123[p12]→4567[p11]→891011[p10]→***************************************/void Check_Key(void){unsigned char hang ,lie,tmp1,tmp2;unsigned char keymap[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};//设置键盘逻辑键值与程序计算键值的映射tmp1 = 0x08;for(hang = 0;hang < 4;hang++)//行扫描{KEY_OUT = 0x0f;//P1.0~P1.3输出全1KEY_OUT -= tmp1;//P1.0~p1.3输出四位中有一个为0tmp1 >>=1;if((KEY_IN & 0xf0)<0xf0)//是否P1IN的P1.4~P1.7中有一位为0{tmp2 = 0x10;// tmp2用于检测出哪一位为0for(lie = 0;lie < 4;lie++)//列检测{if((KEY_IN & tmp2) == 0x00)//是否是该列,等于0为是{Key_Val = keymap[hang*4 + lie];//获取键值return;//退出循环}tmp2 <<= 1;// tmp2右移1位}}}}/*******************************************函数名称:delay功能:延时约15ms,完成消抖功能参数:无返回值:t= tmp*5*clk根据使用时钟调整tmp值********************************************/void delay(void){unsigned int tmp;for(tmp = 12000;tmp > 0;tmp--);}/*******************************************函数名称:Key_Event功能:检测按键,并获取键值参数:无返回值:无********************************************/ void Key_Event(void){unsigned char tmp;KEY_OUT=0;设置P1OUT全为0,等待按键输入tmp=KEY_IN;获取p1INif((tmp&0xf0)<0xf0)键按下{delay();除抖动Check_Key();调用check_Key(),获取键值switch(Key_Val)//P2.0~P2.3接发光二极管,测试程序用{case 0:P2DIR|=BIT0;P2OUT |=BIT0;delay();P2OUT ^=BIT0;break;case 1:P2DIR|=BIT1;P2OUT |=BIT1; delay();P2OUT ^=BIT1;break;case 2:P2DIR|=BIT2;P2OUT |=BIT2; delay();P2OUT ^=BIT2;break;case 3:P2DIR|=BIT3;P2OUT |=BIT3; delay();P2OUT ^=BIT3;break;case 4:P2DIR|=BIT0;P2OUT |=BIT0; delay();P2OUT ^=BIT0;break;case 5:P2DIR|=BIT1;P2OUT |=BIT1; delay();P2OUT ^=BIT1;break;case 6:P2DIR|=BIT2;P2OUT |=BIT2; delay();P2OUT ^=BIT2;break;case 7:P2DIR|=BIT3;P2OUT |=BIT3; delay();P2OUT ^=BIT3;break;case 8:P2DIR|=BIT0;P2OUT |=BIT0; delay();P2OUT ^=BIT0;break;case 9:P2DIR|=BIT1;P2OUT |=BIT1; delay();P2OUT ^=BIT1;break;case 10: P2DIR|=BIT2;P2OUT |=BIT2; delay();P2OUT ^=BIT2;break;//////如果有//消//case 11: P2DIR|=BIT3;P2OUT |=BIT3; delay();P2OUT ^=BIT3;break;case 12: P2DIR|=BIT0;P2OUT |=BIT0; delay();P2OUT ^=BIT0;break;case 13: P2DIR|=BIT1;P2OUT |=BIT1; delay();P2OUT ^=BIT1;break;case 14: P2DIR|=BIT2;P2OUT |=BIT2; delay();P2OUT ^=BIT2;break;case 15: P2DIR|=BIT3;P2OUT |=BIT3; delay();P2OUT ^=BIT3;break;default :break;}}}/********************************************************** ***********控制打开或者关闭键盘中断SW= 0:关闭;ELSE:打开***************************************************************** ****/void CtrlKey(unsigned char sw){if(sw==0)KEY_IE =0;//关闭端口中断elseKEY_IE =0xf0; //打开端口中断}/****************************************************************** ***主函数***************************************************************** ****/void main(){WDTCTL=WDTPW+WDTHOLD;//关闭看门狗Init_Keypad();//键盘初始化delay();CtrlKey(1);//键盘打开while(1)Key_Event();//不断扫描,获取键值}/*端口1按键中断*/#pragma vector=PORT1_VECTOR__interrupt void Port(void){if((KEY_IFG&0xf0)!=0){Key_Event();if(Key_Val!=16)//键值!=16有键按下{CtrlKey (0);//关键盘中断}}KEY_IFG=0;KEY_OUT=0;//清中断标志}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#i nclude <MSP430x14x.h>
void Init_Port(void)
{
//将P1口所有的管脚在初始化的时候设置为输入方式 P1DIR = 0;
//将P1口所有的管脚设置为一般I/O口
P1SEL = 0;
// 将P1.4 P1.5 P1.6 P1.7设置为输出方向
P1DIR |= BIT4;
P1DIR |= BIT5;
P1DIR |= BIT6;
P1DIR |= BIT7;
//先输出低电平
P1OUT = 0x00;
// 将中断寄存器清零
P1IE = 0;
P1IES = 0;
P1IFG = 0;
//打开管脚的中断功能
//对应的管脚由高到低电平跳变使相应的标志置位
P1IE |= BIT0;
P1IES |= BIT0;
P1IE |= BIT1;
P1IES |= BIT1;
P1IE |= BIT2;
P1IES |= BIT2;
P1IE |= BIT3;
P1IES |= BIT3;
_EINT();//打开中断
return;
}
void Delay(void)
{
int i;
for(i = 100;i--;i > 0) ;//延时一点时间
}
int KeyProcess(void)
{
int nP10,nP11,nP12,nP13;
int nRes = 0;
//P1.4输出低电平
P1OUT &= ~(BIT4);
nP10 = P1IN & BIT0;
if (nP10 == 0) nRes = 13; nP11 = P1IN & BIT1;
if (nP11 == 0) nRes = 14; nP12 = P1IN & BIT2;
if (nP12 == 0) nRes = 15; nP13 = P1IN & BIT3;
if (nP13 == 0) nRes = 16; //P1.5输出低电平
P1OUT &= ~(BIT4);
nP10 = P1IN & BIT0;
if (nP10 == 0) nRes = 9; nP11 = P1IN & BIT1;
if (nP11 == 0) nRes = 10; nP12 = P1IN & BIT2;
if (nP12 == 0) nRes = 11; nP13 = P1IN & BIT3;
if (nP13 == 0) nRes = 12; //P1.6输出低电平
P1OUT &= ~(BIT4);
nP10 = P1IN & BIT0;
if (nP10 == 0) nRes = 5; nP11 = P1IN & BIT1;
if (nP11 == 0) nRes = 6; nP12 = P1IN & BIT2;
if (nP12 == 0) nRes = 7; nP13 = P1IN & BIT3;
if (nP13 == 0) nRes = 8; //P1.7输出低电平
P1OUT &= ~(BIT4);
nP10 = P1IN & BIT0;
if (nP10 == 0) nRes = 1; nP11 = P1IN & BIT1;
if (nP11 == 0) nRes = 2; nP12 = P1IN & BIT2;
if (nP12 == 0) nRes = 3; nP13 = P1IN & BIT3;
if (nP13 == 0) nRes = 4; P1OUT = 0x00;//恢复以前值。
//读取各个管脚的状态
nP10 = P1IN & BIT0;
nP11 = P1IN & BIT1;
nP12 = P1IN & BIT2;
nP13 = P1IN & BIT3;
for(;;)
{
if(nP10 == 1 && nP11 == 1 && nP12 == 1 && nP13 == 1) {
//等待松开按键
break;
}
}
return nRes;
}
// 处理来自端口 1 的中断
interrupt [PORT1_VECTOR] void PORT_ISR(void)
{
Delay();
KeyProcess();
if(P1IFG & BIT0)
{
P1IFG &= ~(BIT0);// 清除中断标志位
}
if(P1IFG & BIT1)
{
P1IFG &= ~(BIT1);// 清除中断标志位
}
if(P1IFG & BIT2)
{
P1IFG &= ~(BIT2);// 清除中断标志位
}
if(P1IFG & BIT3)
{
P1IFG &= ~(BIT3);// 清除中断标志位
}
}
void Init_CLK(void)
{
unsigned int i;
BCSCTL1 = 0X00; //将寄存器的内容清零
//XT2震荡器开启
//LFTX1工作在低频模式
//ACLK的分频因子为1
do
{
IFG1 &= ~OFIFG; // 清除OSCFault标志
for (i = 0x20; i > 0; i--);
}
while ((IFG1 & OFIFG) == OFIFG); // 如果OSCFault =1
BCSCTL2 = 0X00; //将寄存器的内容清零
BCSCTL2 += SELM1; //MCLK的时钟源为TX2CLK,分频因子为1
BCSCTL2 += SELS; //SMCLK的时钟源为TX2CLK,分频因子为1
}。