如果不使用定时器,会有很多冲突。比如数码管显示不正常,按键响应问题。
定时器时间消隐效果还不错,根据实验室另一个光伏项目的朋友用stc15代码改过来的。
数码管
#ifndef __LED_H
#define __LED_H
#include "sys.h"
#define DX0 PAout(0)
#define DX1 PAout(1)
#define DX2 PAout(2)
#define DX3 PAout(3)
#define DX4 PAout(4)
#define DX5 PAout(5)
#define DX6 PAout(6)
#define DX7 PAout(7)
#define LED1 PAout(8)
#define LED2 PAout(9)
#define LED3 PAout(10)
#define LED4 PAout(11)
#define LED5 PAout(12)
#define LED6 PCout(8)
#define Beep PGout(9)
#define D0 PEout(0)
#define D1 PEout(1)
#define D2 PEout(2)
#define D3 PEout(3)
void LED_Init(void);
void Display(u8 index);
#endif
#include "led.h"
u8 seg_tab[17] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,\
0x88,0x83,0xC6,0xA1,0x86,0x8E,0xBF};
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOG, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_SetBits(GPIOE,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC,GPIO_Pin_8);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOG, &GPIO_InitStructure);
GPIO_SetBits(GPIOG,GPIO_Pin_9);
TIM_DeInit( TIM6 ); //将TIM6寄存器重置为缺省值
TIM_InternalClockConfig( TIM6 );
TIM_TimeBaseStructure.TIM_Period=10; //扫描周期5ms
TIM_TimeBaseStructure.TIM_Prescaler=35999;
TIM_TimeBaseStructure.TIM_ClockDivision=0;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM6,&TIM_TimeBaseStructure);
TIM_ClearFlag( TIM6, TIM_FLAG_Update ); //清除溢出中断标志位
TIM_ARRPreloadConfig( TIM6, DISABLE ); //禁止ARR预装载缓冲器
TIM_ITConfig( TIM6,TIM_IT_Update,ENABLE );// 打开更新事件中断
TIM_Cmd(TIM6,ENABLE); //使能TIM6
}
void Display(u8 index)
{
DX0 = seg_tab[index]&0x01;
DX1 = (seg_tab[index]>>1)&0x01;
DX2 = (seg_tab[index]>>2)&0x01;
DX3 = (seg_tab[index]>>3)&0x01;
DX4 = (seg_tab[index]>>4)&0x01;
DX5 = (seg_tab[index]>>5)&0x01;
DX6 = (seg_tab[index]>>6)&0x01;
DX7 = (seg_tab[index]>>7)&0x01;
}
- 中断服务函数
void TIM6_IRQHandler() //数码管扫描
{
if(TIM_GetITStatus(TIM6,TIM_IT_Update)!=RESET)
{
D0=D1=D2=D3=1;
switch(s)
{
case 1:D0=0;Display(t1);break;
case 2:D1=0;Display(t2);break;
case 3:D2=0;Display(t3);break;
case 4:D3=0;Display(t4);break;
}
s++; if(s>4) s=1;
TIM_ClearITPendingBit(TIM6,TIM_IT_Update);
}
}
#include "key.h"
#include "led.h"
#include "sys.h"
#define PORT GPIOF->IDR
//行接PF0-3,列接FD4-7
void KEY_Init()
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7,ENABLE); //TIM7按键扫描
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE);//使能PF口时钟
TIM_DeInit( TIM7 ); //将TIM6寄存器重置为缺省值
TIM_InternalClockConfig( TIM7 );
TIM_TimeBaseStructure.TIM_Period=20; //扫描周期10ms
TIM_TimeBaseStructure.TIM_Prescaler=35999;
TIM_TimeBaseStructure.TIM_ClockDivision=0;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM7,&TIM_TimeBaseStructure);
TIM_ClearFlag( TIM7, TIM_FLAG_Update ); //清除溢出中断标志位
TIM_ARRPreloadConfig( TIM7, DISABLE ); //禁止ARR预装载缓冲器
TIM_ITConfig( TIM7,TIM_IT_Update,ENABLE );// 打开更新事件中断
TIM_Cmd(TIM7,ENABLE);
}
s8 scan_MatrixKey()
{
u8 column;//列
u8 row;//行
u8 tmp;//临时变量
s8 MatrixKey_value = 20;//初始值不能为0~15
static u8 key_count = 0;//按键被中断扫描的次数
///IO口的配置/
//低8位为推挽输出
GPIOF->CRL &= 0X00000000;
GPIOF->CRL |= 0X33333333;
//初值:低4位为低,次低4位为高
GPIOF->ODR &= 0XFF00;
GPIOF->ODR |= 0X00F0;
//次低4位为上拉输入
GPIOF->CRL &= 0X0000FFFF;
GPIOF->CRL |= 0X88880000;
tmp = PORT;//必须要
if (tmp != 0XF0)//如果有键按下
{
//防止长按时,持续自增导致变量溢出
if (key_count <= 2)
{
key_count++;
}
}
//若产生抖动按键被抬起则计数清0
else
key_count = 0;
//若按键连续2次扫描均处于按下状态
//则认为按键确实被按下了
if (key_count == 2)
{
column = tmp & 0X00F0;//获取列号
///IO口的配置/
//低8位为推挽输出
GPIOF->CRL &= 0X00000000;
GPIOF->CRL |= 0X33333333;
//翻转:低4位为高,次低4位为低
GPIOF->ODR &= 0XFF00;
GPIOF->ODR |= 0X000F;//低4位为高,次低4位为低
//低4位为上拉输入
GPIOF->CRL &= 0XFFFF0000;
GPIOF->CRL |= 0X00008888;
row = PORT & 0X000F;//获取行号
switch (column | row)//column|row为按键被按下对应端口的编码
{
//按键对应的码表(可以根据需求调整欲返回的键值)
case 0XEE: MatrixKey_value = 1; break; //S1
case 0XDE: MatrixKey_value = 2; break;
case 0XBE: MatrixKey_value = 3; break;
case 0X7E: MatrixKey_value = 4; break;
case 0XED: MatrixKey_value = 5; break;
case 0XDD: MatrixKey_value = 6; break;
case 0XBD: MatrixKey_value = 7; break;
case 0X7D: MatrixKey_value = 8; break; //S8
case 0XEB: MatrixKey_value = 9; break;
case 0XDB: MatrixKey_value = 10; break;
case 0XBB: MatrixKey_value = 11; break;
case 0X7B: MatrixKey_value = 12; break;
case 0XE7: MatrixKey_value = 13; break;
case 0XD7: MatrixKey_value = 14; break;
case 0XB7: MatrixKey_value = 15; break;
case 0X77: MatrixKey_value = 16; break; //S16
default : break;
}
}
//若没有按键被按下(已松手)则扫描次数清0
//方便下次按下扫描计数
if ((PORT & 0X00FF) == 0x00F0)
{
key_count = 0;
}
return MatrixKey_value;
}
记得添加外部全局变量
这个按键扫描函数是从别人博客上用的。
void key_FUC()
{
key_value=scan_MatrixKey();
if(key_value==1) //S1模式选择
{
flag_mode++;
LCD_Clear(BACK_COLOR);delay_ms(25);
if(flag_mode==1) {dianji(0,5999); t3=3;t4=0; }
else if(flag_mode==2) { delay_ms(25);dianji(1,6999); t3=6;t4=0; }
else if(flag_mode==3) { delay_ms(25);dianji(1,5999);t3=1;t4=0; }
else { LED1=LED2=LED3=LED4=LED5=LED6=1; LED4=0;dianji(1,7999);t3=1;t4=0; }
if(flag_mode>5) //暂停后再次按下,
{
if(flag_mode==7) flag_mode=0; //之前遇到bug,模式走完stop后再次按S1就不显示界面了,我的算法很垃圾
flag_mode= mode_t+1; //stop模式按下S1后,到下一个模式
if(flag_mode>4) flag_mode=0; //防止立即进入模式1导致计数从10开始的bug,目前还没想修复
}
}
else if(key_value==2) //重复进入自检,但是再次按任意键时得两次
{
LCD_Clear(BACK_COLOR);
dianji(0,9999);
flag_mode=7;
}
else if(key_value==3) //停止按钮
{
dianji(0,9999);
flag_mode=5;
}
else if(key_value==4)
{
bj_set-=1;
}
else if(key_value==5)
{
bj_set+=1;
}
else ;
}
void TIM7_IRQHandler() //按键
{
if(TIM_GetITStatus(TIM7,TIM_IT_Update)!=RESET)
{
scan_MatrixKey();
key_FUC();
TIM_ClearITPendingBit(TIM7,TIM_IT_Update);
}
}
这个按键里的程序是我之前练习一个单片机省赛题目写的,以后有空聊