/*******原程序**********/
#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 , VOID funtion1 , VOID funtion2)
{ //3、第一个参数为LED点亮时长,第二位灭时长,三为亮函数,四为灭函数
led_on_time = led_on_time_temp ;
led_off_time = led_off_time_temp ;
if(flag1 == 1)
{
flag1 = 0 ;
funtion_run = funtion1 ; //指针指向亮函数
funtion_run() ; //并运行所指向的函数
}
if(flag2 == 1)
{
flag2 = 0 ;
funtion_run = funtion2 ; //指针指向灭函数
funtion_run() ; //并运行所指向的函数
}
}
/*******************************************************************************************************************************/
//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 ;
}
/************************************************************************************************
// adc_value = adc_hex2dec(adc_result()) ;
// if((adc_value>=0) && (adc_value<=5000)) //若是有按键按下,则按键对号
// {
// if(0 == adc_value)
// return 9;
// else if((adc_value < 723) && (adc_value > 323)) //+-200mV
// return 8;
// else if((adc_value < 1254) && (adc_value > 854))
// return 7;
// else if((adc_value < 1742) && (adc_value > 1342))
// return 6;
// else if((adc_value < 2338) && (adc_value > 1938))
// return 5;
// else if((adc_value < 2778) && (adc_value > 2378))
// return 4;
// else if((adc_value < 3237) && (adc_value > 2837))
// return 3;
// else if((adc_value < 3793) && (adc_value > 3393))
// return 2;
// else if((adc_value < 4306) && (adc_value > 3906))
// return 1;
//// else if((adc_value <= 5000) && (adc_value > 4795-244)) //无按键按下
//// return 10;
// }
// else //出错,则返回0
// {
// return 0 ;
// }
**************************************************************************************************/
}
/*****************************************
*****************************************/
u8 key_scan(void) //状态机函数,返回状态机键值
{
static u8 key_statues = key_statues0 ; //相当于锁,函数运行前与运行完,都要置0
static u8 adc_key_number_temp ;
u8 key_return ;
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值
#if 0
// switch (key_number) //若是按下有效,则将代码段放在此处
// {
// 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 10 : //该处移往松手态
//// {
//// key_return = key10 ;
//// }
//// break ;
#endif
}
}
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,即初始态。相当于自锁
// key_return = key10 ; //松手返回key10
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)
{
// buzz_run(key_return_number) ;
// u8 i = 0 ;
switch(key_return_number)
{
case key1 :
set_timer(20 , 20 , led_on , led_off) ;
break ;
case key2 :
set_timer(60 , 60 , led_on , led_off) ;
break ;
case key3 :
set_timer(200 , 200 , led_on , led_off) ;
break ;
case key4 :
set_timer(1000 , 1000 , led_on , led_off) ;
break ;
case key5 :
set_timer(2000 , 2000 , led_on , led_off) ;
break ;
case key6 :
set_timer(3000 , 3000 , led_on , led_off) ;
break ;
case key7 :
set_timer(4000 , 4000 , led_on , led_off) ;
break ;
case key8 :
set_timer(5000 , 5000 , led_on , led_off) ;
break ;
case key9 :
set_timer(6000 , 6000 , buzz_on , buzz_off) ;
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)
// set_timer(6000 , 500 , led_on , led_off) ;
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)) //3、(led_on_time+led_off_time)是整个中断周期的时间,led_off_time在这里才现身
soft_timer_counter = 0 ; //清0
if(soft_timer_counter < led_on_time) //1、这两个if最为重要,若是小于,则置位flag1
flag1 = 1 ;
else //2、否则,置位flag2,通过if和else组合,将一段时间一分为2,控制LED亮灭时间//注意,在此并未设置熄灭LED的时间长度,而是通过后面的led_off_time来控制
flag2 = 1 ;
}
结贴!!!!!!只改一条语句。。改if(soft_timer_counter == (led_on_time+led_off_time))为if(soft_timer_counter >= (led_on_time+led_off_time))。。。。。。。多谢各位耐心解答,谢谢!