如下代码程序运行效果与个人设计不符
//*********************************************************
#include "SYSCFG.h"
//***********************宏定义****************************
typedef unsigned char u8;
#define Key PA4
//***********************变量定义****************************
static u8 TimeCnt = 0; //记录按下时长,刻10ms
static u8 lock = 0; //lock变量用于判断是否是第一次进行按键确认状态
typedef enum
{KEY_CHECK = 0, //检测状态KEY_COMFIRM = 1, //按键确认,已经识别到了前沿抖动KEY_RELEASE = 2 //按键释放,
}KEY_STATE;
static KeyState =0; // 初始化按键状态为检测状态
static u8 g_KeyFlag = 0; // 按键有效标志,0: 按键值无效; 1:按键值有效
typedef enum
{NULL_KEY = 0,SHORT_KEY =1,LONG_KEY=2
}KEY_TYPE;
static KEY_TYPE g_KeyActionFlag; //用于区别长按和短按static int shortCnt;
static int longtCnt;/***/
void Key_Scan(void)
{ switch (KeyState){//按键未按下状态,此时判断Key的值case 0: if(!Key) {KeyState = 1; //如果按键Key值为0,说明按键开始按下,进入下一个状态 }TimeCnt = 0; break;case 1:if(!Key) //查看当前Key是否还是0,还是就计数加一{ TimeCnt++; if(TimeCnt > 61) {}if(TimeCnt > 8) {}} else // 不还是0,按键释放了{KeyState = 2;TimeCnt = 0; //计数复位} break;case 2:if(Key) //当前Key值为1,说明按键已经释放,返回开始状态{ KeyState = 0; }break;default: break;}
}
/*-------------------------------------------------* 函数名:interrupt ISR* 功能: 定时器0的中断处理* 输入: 无* 输出: 无--------------------------------------------------*/
void interrupt ISR(void)
{ static u8 cnt; if(T0IE && T0IF) //开定时器/计数器0中断&&中断标志置位{cnt++;if(cnt>2) // 每 8.16*n ms执行一次按键扫描程序{Key_Scan();cnt = 0;}T0IF = 0; //清零time0中断标志}
} /*-------------------------------------------------* 函数名称: TIMER0_INITIAL* 功能: 初始化设置定时器0* 设置TMR0定时时长=(1/系统时钟频率)*指令周期*预分频值*255* =(1/16000000)*2*256*255=8.16ms -------------------------------------------------*/
void TIMER0_INITIAL (void)
{OPTION = 0B00000111;//Bit5: T0CS Timer0时钟源选择 // 1-外部引脚电平变化T0CKI 0-内部时钟(FOSC/2)//Bit4: T0CKI引脚触发方式 1-下降沿 0-上升沿//Bit3: PSA 预分频器分配位 0-Timer0 1-WDT //Bit[2:0]: PS2 8个预分频比 111 - 1:256T0IF = 0; //清空T0软件中断
}//***********************函数声明**************************
void configurate_initial(void); //上电系统初始化/*-------------------------------------------------
* 函数名:main
* 功能: 主函数
* 输入: 无
* 输出: 无--------------------------------------------------*/
void main()
{u8 i=0;//上电初始化configurate_initial(); //初始化配置TIMER0_INITIAL(); //每8.16ms 执行一次按键扫描程序GIE = 1; //开中断T0IE = 1; //开定时器/计数器0中断u8 switch11=0;
// PA7=1;//开启电源
// PC3=1;//开启激光发射器//上电初始化完毕后while(1){if(KeyState==1&&TimeCnt > 61) //16ms*61=1s{PA7=1;//开启电源PC3=1;//开启激光发射器if(i==1){PA7=0;//关闭电源}i++;}// if(KeyState==1&&TimeCnt > 8) //16ms*8=128ms
// {
// PC3=~PC3;//取反激光发射器的开关
// }}
}/*-------------------------------------------------
* 函数名:POWER_INITIAL
* 功能: 上电系统初始化
* 输入: 无
* 输出: 无--------------------------------------------------*/
void configurate_initial(void)
{ //中断与时钟配置OSCCON = 0B01110001; //IRCF=111=16MHz/2T=8MHz,0.125usINTCON = 0; //暂禁止所有中断PORTA = 0B00000000; //将PA0~7的引脚状态初始为0PORTC = 0B00000000; //将PC0~7的引脚状态初始为0OPTION = 0B00001000; //地址OPTION处的Bit3控制看门狗时钟和时钟0的共用分频电路归谁。为1归看门狗,Bit2~0是分频电路的分频系数PS=000MSCKCON = 0B00000000; //地址MSCKCON处的Bit6->0,禁止PA4,PC5稳压输出; Bit5->0,TIMER2时钟为Fosc; Bit4->0,禁止LVR CMCON0 = 0B00000111; //关闭比较器,CxIN为数字IO口//PA4TRISA = 0B00010000; //地址TRISA处的Bit4=1,表输入WPUA = 0B00010000; //地址WPUA处的Bit4=1,表开上拉//PC3 TRISC = 0B00000000; //地址TRISA处的Bit3=0,表输出WPUC = 0B00001000; //地址WPUA处的Bit3=0,表开上拉//PA7TRISA = 0B00000000; //地址TRISA处的Bit7=0,表输出WPUA = 0B10000000; //地址WPUA处的Bit7=1,表开上拉
}
去掉一些代码,希望多按几次按键后引脚PC3可以在示波器上出现上升沿和下降沿。
事实是PC3一直保存高电平
//*********************************************************
#include "SYSCFG.h"
//***********************宏定义****************************
typedef unsigned char u8;
#define Key PA4
//***********************变量定义****************************
static u8 TimeCnt = 0; //记录按下时长,刻10msstatic KeyState =0; // 初始化按键状态为检测状态/***/
void Key_Scan(void)
{ switch (KeyState){//按键未按下状态,此时判断Key的值case 0: if(!Key) {KeyState = 1; //如果按键Key值为0,说明按键开始按下,进入下一个状态 PC3=1;}TimeCnt = 0; break;case 1:if(!Key) //查看当前Key是否还是0,还是就计数加一{ TimeCnt++; } else // 不还是0,按键释放了{KeyState = 2;PC3=0;TimeCnt = 0; //计数复位} break;case 2:if(Key) //当前Key值为1,说明按键已经释放,返回开始状态{ KeyState = 0; PC3=1; }break;default: break;}
}
/*-------------------------------------------------* 函数名:interrupt ISR* 功能: 定时器0的中断处理* 输入: 无* 输出: 无--------------------------------------------------*/
void interrupt ISR(void)
{ static u8 cnt; if(T0IE && T0IF) //开定时器/计数器0中断&&中断标志置位{cnt++;if(cnt>2) // 每 8.16*n ms执行一次按键扫描程序{Key_Scan();cnt = 0;}T0IF = 0; //清零time0中断标志}
} /*-------------------------------------------------* 函数名称: TIMER0_INITIAL* 功能: 初始化设置定时器0* 设置TMR0定时时长=(1/系统时钟频率)*指令周期*预分频值*255* =(1/16000000)*2*256*255=8.16ms -------------------------------------------------*/
void TIMER0_INITIAL (void)
{OPTION = 0B00000111;//Bit5: T0CS Timer0时钟源选择 // 1-外部引脚电平变化T0CKI 0-内部时钟(FOSC/2)//Bit4: T0CKI引脚触发方式 1-下降沿 0-上升沿//Bit3: PSA 预分频器分配位 0-Timer0 1-WDT //Bit[2:0]: PS2 8个预分频比 111 - 1:256T0IF = 0; //清空T0软件中断
}/*-------------------------------------------------
* 函数名:POWER_INITIAL
* 功能: 上电系统初始化
* 输入: 无
* 输出: 无--------------------------------------------------*/
void configurate_initial(void)
{ //中断与时钟配置OSCCON = 0B01110001; //IRCF=111=16MHz/2T=8MHz,0.125usINTCON = 0; //暂禁止所有中断PORTA = 0B00000000; //将PA0~7的引脚状态初始为0PORTC = 0B00000000; //将PC0~7的引脚状态初始为0OPTION = 0B00001000; //地址OPTION处的Bit3控制看门狗时钟和时钟0的共用分频电路归谁。为1归看门狗,Bit2~0是分频电路的分频系数PS=000MSCKCON = 0B00000000; //地址MSCKCON处的Bit6->0,禁止PA4,PC5稳压输出; Bit5->0,TIMER2时钟为Fosc; Bit4->0,禁止LVR CMCON0 = 0B00000111; //关闭比较器,CxIN为数字IO口//PA4TRISA = 0B00010000; //地址TRISA处的Bit4=1,表输入WPUA = 0B00010000; //地址WPUA处的Bit4=1,表开上拉//PC3 TRISC = 0B00000000; //地址TRISA处的Bit3=0,表输出WPUC = 0B00001000; //地址WPUA处的Bit3=0,表开上拉//PA7TRISA = 0B00000000; //地址TRISA处的Bit7=0,表输出WPUA = 0B10000000; //地址WPUA处的Bit7=1,表开上拉
}/*-------------------------------------------------
* 函数名:main
* 功能: 主函数
* 输入: 无
* 输出: 无--------------------------------------------------*/
void main()
{//上电初始化configurate_initial(); //初始化配置TIMER0_INITIAL(); //每8.16ms 执行一次按键扫描程序GIE = 1; //开中断T0IE = 1; //开定时器/计数器0中断PA7=1;//开启电源PC3=1;//开启激光发射器//上电初始化完毕后while(1){}
}
去掉了函数Key_Scan。改成PC3=~PC3;希望可以在示波器上看到方波,每隔8.16ms变换一次电频。
成功输出了:
问题就在函数Key_Scan中。
//*********************************************************
#include "SYSCFG.h"
//***********************宏定义****************************
typedef unsigned char u8;
#define Key PA4
//***********************变量定义****************************
static u8 TimeCnt = 0; //记录按下时长,刻10msstatic KeyState =0; // 初始化按键状态为检测状态/***/
void Key_Scan(void)
{ switch (KeyState){//按键未按下状态,此时判断Key的值case 0: if(!Key) {KeyState = 1; //如果按键Key值为0,说明按键开始按下,进入下一个状态 PC3=1;}TimeCnt = 0; break;case 1:if(!Key) //查看当前Key是否还是0,还是就计数加一{ TimeCnt++; } else // 不还是0,按键释放了{KeyState = 2;PC3=0;TimeCnt = 0; //计数复位} break;case 2:if(Key) //当前Key值为1,说明按键已经释放,返回开始状态{ KeyState = 0; PC3=1; }break;default: break;}
}
/*-------------------------------------------------* 函数名:interrupt ISR* 功能: 定时器0的中断处理* 输入: 无* 输出: 无--------------------------------------------------*/
void interrupt ISR(void)
{ static u8 cnt; if(T0IE && T0IF) //开定时器/计数器0中断&&中断标志置位{cnt++;if(cnt>2) // 每 8.16*n ms执行一次按键扫描程序{PC3=~PC3;cnt = 0;}T0IF = 0; //清零time0中断标志}
} /*-------------------------------------------------* 函数名称: TIMER0_INITIAL* 功能: 初始化设置定时器0* 设置TMR0定时时长=(1/系统时钟频率)*指令周期*预分频值*255* =(1/16000000)*2*256*255=8.16ms -------------------------------------------------*/
void TIMER0_INITIAL (void)
{OPTION = 0B00000111;//Bit5: T0CS Timer0时钟源选择 // 1-外部引脚电平变化T0CKI 0-内部时钟(FOSC/2)//Bit4: T0CKI引脚触发方式 1-下降沿 0-上升沿//Bit3: PSA 预分频器分配位 0-Timer0 1-WDT //Bit[2:0]: PS2 8个预分频比 111 - 1:256T0IF = 0; //清空T0软件中断
}/*-------------------------------------------------
* 函数名:POWER_INITIAL
* 功能: 上电系统初始化
* 输入: 无
* 输出: 无--------------------------------------------------*/
void configurate_initial(void)
{ //中断与时钟配置OSCCON = 0B01110001; //IRCF=111=16MHz/2T=8MHz,0.125usINTCON = 0; //暂禁止所有中断PORTA = 0B00000000; //将PA0~7的引脚状态初始为0PORTC = 0B00000000; //将PC0~7的引脚状态初始为0OPTION = 0B00001000; //地址OPTION处的Bit3控制看门狗时钟和时钟0的共用分频电路归谁。为1归看门狗,Bit2~0是分频电路的分频系数PS=000MSCKCON = 0B00000000; //地址MSCKCON处的Bit6->0,禁止PA4,PC5稳压输出; Bit5->0,TIMER2时钟为Fosc; Bit4->0,禁止LVR CMCON0 = 0B00000111; //关闭比较器,CxIN为数字IO口//PA4TRISA = 0B00010000; //地址TRISA处的Bit4=1,表输入WPUA = 0B00010000; //地址WPUA处的Bit4=1,表开上拉//PC3 TRISC = 0B00000000; //地址TRISA处的Bit3=0,表输出WPUC = 0B00001000; //地址WPUA处的Bit3=0,表开上拉//PA7TRISA = 0B00000000; //地址TRISA处的Bit7=0,表输出WPUA = 0B10000000; //地址WPUA处的Bit7=1,表开上拉
}/*-------------------------------------------------
* 函数名:main
* 功能: 主函数
* 输入: 无
* 输出: 无--------------------------------------------------*/
void main()
{//上电初始化configurate_initial(); //初始化配置TIMER0_INITIAL(); //每8.16ms 执行一次按键扫描程序GIE = 1; //开中断T0IE = 1; //开定时器/计数器0中断PA7=1;//开启电源PC3=1;//开启激光发射器//上电初始化完毕后while(1){}
}
中断程序可以按照设定的时间,一次又一次的执行。
中断函数里的Key_Scan函数却不能正常执行。
PC3恒为1,所以PC3=0没有被执行。
PC3=0要执行的话,Key就要等于0。
所以Key一直没有等于0,一直为1。
为什么一直为1?
设计是要Key,即引脚PA4做上拉输入。当按键按下时被拉低为0。
看看PA4的配置
void configurate_initial(void)
{ //中断与时钟配置OSCCON = 0B01110001; //IRCF=111=16MHz/2T=8MHz,0.125usINTCON = 0; //暂禁止所有中断PORTA = 0B00000000; //将PA0~7的引脚状态初始为0PORTC = 0B00000000; //将PC0~7的引脚状态初始为0OPTION = 0B00001000; //地址OPTION处的Bit3控制看门狗时钟和时钟0的共用分频电路归谁。为1归看门狗,Bit2~0是分频电路的分频系数PS=000MSCKCON = 0B00000000; //地址MSCKCON处的Bit6->0,禁止PA4,PC5稳压输出; Bit5->0,TIMER2时钟为Fosc; Bit4->0,禁止LVR CMCON0 = 0B00000111; //关闭比较器,CxIN为数字IO口//PA4TRISA = 0B00010000; //地址TRISA处的Bit4=1,表输入WPUA = 0B00010000; //地址WPUA处的Bit4=1,表开上拉//PC3 TRISC = 0B00000000; //地址TRISA处的Bit3=0,表输出WPUC = 0B00001000; //地址WPUA处的Bit3=0,表开上拉//PA7TRISA = 0B00000000; //地址TRISA处的Bit7=0,表输出WPUA = 0B10000000; //地址WPUA处的Bit7=1,表开上拉
}
可以发现PA4被配置成了关闭上拉的输出。祸根就是它。
上一篇:理解与实现线程池