Stm32管脚控制共阳数码管LED数码管
总体电路部分。
LED数码管驱动部分
MCU控制部分
下面为程序部分
程序用定时器定时扫描出每一位的数码管。
对所需要的变量进行定义
extern u32 Timer4_overrun; //定时器自加计数值
extern uint32_t Timer4_count; //定时器自加计数值
//--- 显示0~9笔段代码表 ---
unsigned char LEDSEG[] =
{
0x03,0x9F,0x25,0x0D,0x99,0x49,0x41,0x1F,0x01,0x09,
};
//--- 数码管显示的位选通段代码表 ---
unsigned char LEDDIG[] =
{
0x80,0x40,0x20,0x10
};
unsigned char LEDBuffer[4]; //--- 定义的显示缓冲区 ---
unsigned char LEDPointer = 0; //--- 定义的扫描计数变量 ---
unsigned int msCounter = 0;
u32 Counter = 0; //计数
u16 Twinkle = 0;
u16 Twinkle_ms = 0;
u16 Twinkle_cq = 0;
将引脚和定时器进行初始化。
/**
* 函数功能: 配置TIM4定时器初始化
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void Tim4_init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/*-------------------中断优先级配置初始化-------------------*/
/* 设置中断组为0 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* 设置中断来源 */
NVIC_InitStructure.NVIC_IRQChannel = ADVANCE_TIM4_IRQ;
/* 设置主优先级为 0 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
/* 设置抢占优先级为3 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/*-------------------TIM4配置初始化-------------------*/
/* 开启TIM4_CLK即内部时钟CK_INT=72M */
RCC_APB1PeriphClockCmd(ADVANCE_TIM4_CLK, ENABLE);
/* 自动重装载寄存器周的值(计数值) */
TIM_TimeBaseStructure.TIM_Period=ADVANCE_TIM4_PERIOD;
/* 累计 TIM_Period个频率后产生一个更新或者中断
时钟预分频数为71,则驱动计数器的时钟CK_CNT = CK_INT / (71+1)=1M */
TIM_TimeBaseStructure.TIM_Prescaler= ADVANCE_TIM4_PRESCALER;
/* 计数器计数模式,基本定时器TIM8向上计数 */
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
/* 初始化定时器TIM4 */
TIM_TimeBaseInit(ADVANCE_TIM4, &TIM_TimeBaseStructure);
/* 清除计数器中断标志位 */
TIM_ClearITPendingBit(ADVANCE_TIM4, TIM_IT_Update);
/* 开启计数器中断 */
TIM_ITConfig(ADVANCE_TIM4,TIM_IT_Update,ENABLE);
/* 使能计数器 */
TIM_Cmd(ADVANCE_TIM4, ENABLE);
}
/**
* 函数功能: LED灯管脚初始化
* 输入参数: 无
* 返 回 值: 无
* 说 明:此处用到了特殊引脚,需要将RTC和外部低速时钟引脚作为普通引脚定义。
*/
void Hxeled_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(LED_SCK_CLK, ENABLE); //使能PA端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//失能JTAG
PWR_BackupAccessCmd( ENABLE );/* 允许修改RTC和后备寄存器*/
RCC_LSEConfig( RCC_LSE_OFF ); /* 关闭外部低速时钟,PC14+PC15可以用作普通IO*/
BKP_TamperPinCmd(DISABLE); /* 关闭入侵检测功能,PC13可以用作普通IO*/
GPIO_InitStructure.GPIO_Pin = LED1_A_OUT | LED1_B_OUT | LED1_C_OUT | LED1_D_OUT |LED1_E_OUT |LED1_F_OUT | LED1_G_OUT | LED1_DP_OUT | LED2_G_OUT | LED2_DP_OUT | LED2_C_OUT | LED_WE1 | LED_WE2 | LED_WE3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化
GPIO_InitStructure.GPIO_Pin = LED2_A_OUT | LED2_B_OUT | LED2_D_OUT |LED2_E_OUT |LED2_F_OUT;
GPIO_Init(GPIOB, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz
PWR_BackupAccessCmd(DISABLE);/* 禁止修改RTC和后备寄存器*/
GPIO_InitStructure.GPIO_Pin = LED_WE4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOC,&GPIO_InitStructure);
DIG1=0;
DIG2=0;
DIG3=0;
DIG4=0;
A_out = 0;
B_out = 0;
C_out = 0;
D_out = 0;
E_out = 0;
F_out = 0;
G_out = 0;
DP_out = 1;
}
显示的数字和闪烁时间
/**
* 函数功能: 将数据传递给数码管显示,
* 输入参数1: data:所显示的数据
* 输入参数2:twinkle:闪烁时间;单位
* 返 回 值: 无
* 说 明:无
*/
void Display_data(u32 data , u16 twinkle)
{
Counter = data;
Twinkle = twinkle;
}
此作为核心部分。
/**
* 函数功能: Timer4定时器服务中断函数
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void TIM4_IRQHandler(void)
{
if(TIM_GetITStatus(ADVANCE_TIM4,TIM_IT_Update)!= RESET) //检查指定的TIM中断发生与否:TIM 中断源
{
Timer4_count++;
Twinkle_ms++;
TIM_ClearITPendingBit(ADVANCE_TIM4,TIM_IT_Update); //清除TIMx的中断待处理位:TIM 中断源
//-----------------------------------------------------------------------------------------------
//--- 动态数码管显示扫描驱动程序段 ---
//--- 显示数字 ---
DIG1= 0; //数码管消影
DIG2= 0; //数码管消影
DIG3= 0; //数码管消影
DIG4= 0; //数码管消影
if(0==Twinkle)//不闪烁
{
A_out=((LEDSEG[LEDBuffer[LEDPointer]]>>7) & 0x01);
B_out=((LEDSEG[LEDBuffer[LEDPointer]]>>6) & 0x01);
C_out=((LEDSEG[LEDBuffer[LEDPointer]]>>5) & 0x01);
D_out=((LEDSEG[LEDBuffer[LEDPointer]]>>4) & 0x01);
E_out=((LEDSEG[LEDBuffer[LEDPointer]]>>3) & 0x01);
F_out=((LEDSEG[LEDBuffer[LEDPointer]]>>2) & 0x01);
G_out=((LEDSEG[LEDBuffer[LEDPointer]]>>1) & 0x01);
//DP_out=((LEDSEG[LEDBuffer[LEDPointer]]>>0) & 0x01);
//--- 数码管的位选段选择 ---
DIG1= ((LEDDIG[LEDPointer]>>7) & 0x01);
DIG2= ((LEDDIG[LEDPointer]>>6) & 0x01);
DIG3= ((LEDDIG[LEDPointer]>>5) & 0x01);
DIG4= ((LEDDIG[LEDPointer]>>4) & 0x01);
}
else if(Twinkle_ms > Twinkle)
{
DIG1= 0; //数码管消影
DIG2= 0; //数码管消影
DIG3= 0; //数码管消影
DIG4= 0; //数码管消影
A_out = 0;
B_out = 0;
C_out = 0;
D_out = 0;
E_out = 0;
F_out = 0;
G_out = 0;
DP_out = 0;
Twinkle_cq++;
if(Twinkle_cq > Twinkle)
{
Twinkle_ms = 0;
Twinkle_cq = 0;
}
}
else
{
A_out=((LEDSEG[LEDBuffer[LEDPointer]]>>7) & 0x01);
B_out=((LEDSEG[LEDBuffer[LEDPointer]]>>6) & 0x01);
C_out=((LEDSEG[LEDBuffer[LEDPointer]]>>5) & 0x01);
D_out=((LEDSEG[LEDBuffer[LEDPointer]]>>4) & 0x01);
E_out=((LEDSEG[LEDBuffer[LEDPointer]]>>3) & 0x01);
F_out=((LEDSEG[LEDBuffer[LEDPointer]]>>2) & 0x01);
G_out=((LEDSEG[LEDBuffer[LEDPointer]]>>1) & 0x01);
DP_out=((LEDSEG[LEDBuffer[LEDPointer]]>>0) & 0x01);
//--- 数码管的位选段选择 ---
DIG1= ((LEDDIG[LEDPointer]>>7) & 0x01);
DIG2= ((LEDDIG[LEDPointer]>>6) & 0x01);
DIG3= ((LEDDIG[LEDPointer]>>5) & 0x01);
DIG4= ((LEDDIG[LEDPointer]>>4) & 0x01);
}
}
LEDPointer++; //--- 动态扫描计数变量加1 ---
if(LEDPointer==3)
{
DP_out=0;
}
else
{
DP_out=1;
}
if(sizeof(LEDBuffer) == LEDPointer)LEDPointer = 0; //--- 所有数码管扫描完,计数归0 ---
//-----------------------------------------------------------------------------------------------
//--- 毫秒计数变量加1,并判断1秒是否已到,若到则计数器变量加1并将结果送显示缓冲区 ---
msCounter ++; //--- 毫秒计数变量加1 ---
if(1 == msCounter) //--- 加到1000,表示1秒时间到 ---
{
msCounter = 0;
LEDBuffer[3] = Counter % 10; //--- 将计数器变量的值送到显示缓冲区 ---
LEDBuffer[2] = (Counter/10) % 10;
LEDBuffer[1] = (Counter/100) % 10;
LEDBuffer[0] = (Counter/1000) % 10;
}
}