#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() ; //运行之
}
}