- #include "stc12c5630ad.h"
- typedef unsigned char u8 ;
- typedef unsigned int u16 ;
- #define buzz P32
- #define led P31
- #define adc_key P11
- #define VCC 5000
- u8 aaa = 0 ;
- u8 flag__key_scan ;
- u8 key_number ;
- u8 key_number_final ;
- unsigned char flag1 , flag2 ; //两个软定时标志位,前者为LED亮的时间段,后者为灭
- unsigned int soft_timer_counter , led_on_time , led_off_time ; //软定时自增变量,led亮时间,LED灭时间
- typedef void (*VOID)(void) ; //先定义函数指针
- VOID funtion_run ;
- //void buzz_on(void)
- //{
- // buzz = 1 ;
- //}
- //void buzz_off(void)
- //{
- // buzz = 0 ;
- //}
- void led_on(void)
- {
- led = 0 ;
- }
- void led_off(void)
- {
- led = 1 ;
- }
- void set_timer(u16 led_on_time_temp , u16 led_off_time_temp)
- { //3、第一个参数为LED点亮时长,第二位灭时长
- led_on_time = led_on_time_temp ;
- led_off_time = led_off_time_temp ;
- }
- /*******************************************************************************************************************************/
- //P1M0 , P1M1 , ADC_CONTR=[ADC_POWER][SPEED1][SPEED0][ADC_FLAG] [ADC_START][CHS2][CHS1][CHS0]
- //ADC_DATA , ADC_LOW2,AUXR=[T0x12][T1x12][UART_M0x12][EADCI][ESPI][ELVDI][-][-],IE,IP,IPH
- /*******************************************************************************************************************************/
- #define adc_power_on (ADC_CONTR |= 0x80)
- #define adc_power_off (ADC_CONTR &= 0x7f)
- #define adc_flag_set (ADC_CONTR |= 0x10)
- #define adc_flag_clear (ADC_CONTR &= 0xef)
- #define adc_start_on (ADC_CONTR |= 0x08)
- #define adc_start_off (ADC_CONTR &= 0xf7)
- enum key_number //键值枚举声明
- {
- key1 = 1 , key2 ,
- key3 , key4 ,
- key5 , key6 ,
- key7 , key8 ,
- key9 , key10 //代表未按下
- } ;
- enum key_statues //按键状态枚举,分别为初始状态,按下状态,确认按下状态,松手状态
- {
- key_statues0 = 0 , //初始态
- key_statues1 = 1 , //按下态
- key_statues2 , //确认按下态
- key_statues3 , //松手态
- } ;
- /*****************************************
- *****************************************/
- void adc_init(void) //ADC初始化
- {
- ADC_CONTR = 0x61 ; //0110 0001 //关adc,270个周期转换一次,关标志位,关闭启动位,选择1通道
- adc_power_on ; //重开adc
- adc_start_on ; //开启转换
- adc_flag_clear ; //清adc转换标志位
- }
- u16 adc_result() //获取ADC值
- {
- u16 result = 0 ; //32bit数据装载10bit的adc转换结果值
- u16 value = 0 ;
- adc_init() ;
- while(!(ADC_CONTR & 0x10)) ; //& 0001 0000,若是完成转换,则bit5为1,与上0x10,仍为1,再取反为0,则跳过改行执行下一行
- result = ADC_DATA*4 + ADC_LOW2 ; //ADC_DATA寄存器为8bit,左移两位,再加上ADC_LOW2的值,即可得到转换后完整的10bit结果
- adc_flag_clear ; //清除ADC_FLAG标志位
- return result ;
- }
- u16 adc_hex2dec(float value) //16进制电压值转10进制,单位为mV毫伏
- {
- float value_dec ;
- value_dec = (VCC * (value))/1024 ;
-
- return (u16)value_dec ;
- }
- /*****************************************
- * 00 准双向io口 01 推挽输出
- * 10 高阻输入 11 开漏
- *****************************************/
- void gpio_init() //gpio初始化函数
- {
- P1 = 0x02 ; //0000 0010
- P1M0 = 0x02 ; //0000 0010
- P1M1 = 0x00 ; //0000 0000 设置按键为输入
-
- P3 = 0x06 ; //0000 0110
- P3M0 = 0x00 ; //0000 0000
- P3M1 = 0x06 ; //0000 0110 设置蜂鸣器和LED为输出
- }
- /*****************************************
- *****************************************/
- u8 adc_key_value_process(u16 adc_value) //通过adc值定义键值并返回..........该函数有问题,需要对adc电压值进行更好的处理
- {
- u16 temp_adc_value = adc_value ; //中间变量
- temp_adc_value /= 100 ; //对100求模,若是需要更高精度,可改100为更小值
-
- switch (temp_adc_value) //temp_adc_value精度存在严重问题,建议再用一个switch语句判断键值,使电压值转化为0-10的数字
- {
- case 41 : //按键1按下电压值为4100mV左右
- return 1 ; //返回1
- case 35 :
- return 2 ;
- case 30 :
- return 3 ;
- case 25 :
- return 4 ;
- case 21 :
- return 5 ;
- case 15 :
- return 6 ;
- case 10 :
- return 7 ;
- case 5 :
- return 8 ;
- case 0 :
- return 9 ;
-
- default : //未按下,返回0
- return 0 ;
- }
- }
- /*****************************************
- *****************************************/
- u8 key_scan(void) //状态机函数,返回状态机键值
- {
- static u8 key_statues = key_statues0 ; //相当于锁,函数运行前与运行完,都要置0
- static u8 adc_key_number_temp ;
- u8 key_return = 0 ;
- adc_key_number_temp = adc_key_value_process(adc_hex2dec(adc_result())) ;//采集adc,并转化为键值
- key_number = adc_key_number_temp ;
- switch(key_statues)
- {
- case key_statues0 : //初始态,也相当于锁
- {
- if(0 != key_number) //若是有按键按下,则迁移至状态1------有按键按下时,key_number不会为0
- {
- key_statues = key_statues1 ;
- }
- }
- break ;
-
- case key_statues1 : //按下态
- {
- if(0 == key_number) //如果只是抖动,则返回状态0
- {
- key_statues = key_statues0 ;
- }
-
- else
- {
- key_statues = key_statues2 ; //若是确实有按下,则迁移到状态2
- key_number_final = key_number ; //如果确实有按键按下,则保存先前的key_number值
- }
- }
- break ;
-
- case key_statues2 : //确认按下态,确认按下之后就应该判断是否松手,并进行消抖
- {
- if(0 == key_number) //若已松手,迁移至状态3,相当于松手消抖
- key_statues = key_statues3 ;
- }
- break ;
-
- case key_statues3 : //松手态
- {
- if(0 == key_number) //确实已经松手
- {
- key_statues = key_statues0 ; //如果是确认无按键按下,则将状态迁移回状态0,即初始态。相当于自锁
- adc_key_number_temp = 0 ;
-
- switch (key_number_final) //松手后键值有效
- {
- case 9 :
- key_return = key9 ;
- break ;
-
- case 8 :
- key_return = key8 ;
- break ;
-
- case 7 :
- key_return = key7 ;
- break ;
-
- case 6 :
- key_return = key6 ;
- break ;
-
- case 5 :
- key_return = key5 ;
- break ;
-
- case 4 :
- key_return = key4 ;
- break ;
-
- case 3 :
- key_return = key3 ;
- break ;
-
- case 2 :
- key_return = key2 ;
- break ;
-
- case 1 :
- key_return = key1 ;
- break ;
-
- case 0:
- key_return = key10 ;
- break ;
- }
- }
- else
- {
- key_statues = key_statues2 ; //否则回到状态2,即再判断一次
- }
- }
- break ;
- }
-
- return key_return ;
- }
- void key_process(u8 key_return_number)
- {
- switch(key_return_number)
- {
- case key1 :
- // set_timer(20 , 20 , led_on , led_off) ;
- set_timer(20 , 20) ;
- break ;
-
- case key2 :
- // set_timer(60 , 60 , led_on , led_off) ;
- set_timer(60 , 60) ;
- break ;
-
- case key3 :
- // set_timer(200 , 200 , led_on , led_off) ;
- set_timer(200 , 200) ;
- break ;
-
- case key4 :
- // set_timer(1000 , 1000 , led_on , led_off) ;
- set_timer(1000 , 1000) ;
- break ;
-
- case key5 :
- // set_timer(2000 , 2000 , led_on , led_off) ;
- set_timer(2000 , 2000) ;
- break ;
-
- case key6 :
- // set_timer(3000 , 3000 , led_on , led_off) ;
- set_timer(3000 , 3000) ;
- break ;
-
- case key7 :
- // set_timer(4000 , 4000 , led_on , led_off) ;
- set_timer(4000 , 4000) ;
- break ;
-
- case key8 :
- // set_timer(5000 , 5000 , led_on , led_off) ;
- set_timer(5000 , 5000) ;
- break ;
-
- case key9 :
- // set_timer(6000 , 6000 , buzz_on , buzz_off) ;
- set_timer(6000 , 6000) ;
- break ;
- }
- }
- /*****************************************
- *****************************************/
- void timer0_init(void) //定时器0初始化
- {
- TMOD = 0x01 ;
- TH0 = 0xfc ; //1ms
- TL0 = 0x66 ;
-
- ET0 = 1 ;
- EA = 1 ;
-
- TR0 = 1 ;
- }
- /*****************************************
- *****************************************/
- void main()
- {
- P31 = 1 ;
- gpio_init() ;
- timer0_init() ;
- adc_init() ;
- buzz = 0 ;
- while(1)
- {
- key_process(aaa) ;
- }
- }
- /*****************************************
- *****************************************/
- void timer0_interrupt(void) interrupt 1 //定时器0中断函数,1ms中断
- {
- static u16 tt = 0 ;
-
- TH0 = 0xfc ;
- TL0 = 0x66 ;
-
- tt++ ;
- soft_timer_counter++ ;
- if(tt == 10) //10ms进行一次扫描
- {
- tt = 0 ;
- flag__key_scan = 1 ;
- aaa = key_scan() ;
- }
- if(soft_timer_counter == (led_on_time+led_off_time))
- soft_timer_counter = 0 ; //清0
- if(soft_timer_counter < led_on_time)
- {
- funtion_run = led_on ; //指针指向亮函数
- funtion_run() ; //并运行所指向的函数
- }
- else
- {
- funtion_run = led_off ; //指针指向灭函数
- funtion_run() ; //运行之
- }
- }
现在改成这样也一样,切换很耗时。按键处理感觉不存在问题啊