stm32 时钟带日期显示与LED亮度调节
开发板为正点原子stm32f103nano,基于综合测试实验例程改编。原本准备做计时器功能,但数码管只能显示到原例程的位数,做不出来。就改为保留原例程的RTC任务,ADC任务替换为日期显示,红外遥控任务改为存储数字到变量并把流水灯任务替换为按变量的值调节亮度。
代码如下(这里只给出main.c文件,复制到例程即可),具体说明见注释(被覆盖的程序的代码没有全部删去,请忽略)。
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "includes.h"
#include "key.h"
#include "usart.h"
#include "malloc.h"
#include "smg.h"
#include "rtc.h"
#include "remote.h"
#include "beep.h"
#include "adc.h"
#include "24cxx.h"
#include "norflash.h"
#include "mass_mal.h"
#include "hw_config.h"
#include "memory.h"
#include "timer.h"
int a=0;
/UCOSII任务设置///
//START 任务
//设置任务优先级
#define START_TASK_PRIO 10 //开始任务的优先级设置为最低
//设置任务堆栈大小
#define START_STK_SIZE 64
//任务堆栈
OS_STK START_TASK_STK[START_STK_SIZE];
//任务函数
void start_task(void *pdata);
//ADC任务
//设置任务优先级
#define ADC_TASK_PRIO 7
//设置任务堆栈大小
#define ADC_STK_SIZE 64
//任务堆栈
OS_STK ADC_TASK_STK[ADC_STK_SIZE];
//任务函数
void adc_task(void *pdata);
//遥控任务
//设置任务优先级
#define REMOTE_TASK_PRIO 6
//设置任务堆栈大小
#define REMOTE_STK_SIZE 64
//任务堆栈
OS_STK REMOTE_TASK_STK[REMOTE_STK_SIZE];
//任务函数
void remote_task(void *pdata);
//流水灯任务
//设置任务优先级
#define LEDS_TASK_PRIO 5
//设置任务堆栈大小
#define LEDS_STK_SIZE 64
//任务堆栈
OS_STK LEDS_TASK_STK[LEDS_STK_SIZE];
//任务函数
void leds_task(void *pdata);
//主任务
//设置任务优先级
#define MAIN_TASK_PRIO 4
//设置任务堆栈大小
#define MAIN_STK_SIZE 128
//任务堆栈
OS_STK MAIN_TASK_STK[MAIN_STK_SIZE];
//任务函数
void main_task(void *pdata);
//按键扫描任务
//设置任务优先级
#define KEY_TASK_PRIO 2
//设置任务堆栈大小
#define KEY_STK_SIZE 64
//任务堆栈
OS_STK KEY_TASK_STK[KEY_STK_SIZE];
//任务函数
void key_task(void *pdata);
//
OS_EVENT *msg_key; //按键邮箱事件块
u8 key_event = 0; //按键事件 1:流水灯 2:RTC时钟 3:红外遥控 4:ADC采集 5:USB事件
//共阴数字数组
//0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F, .,全灭
u8 smg_num[] = {0xfc, 0x60, 0xda, 0xf2, 0x66, 0xb6, 0xbe, 0xe0, 0xfe, 0xf6, 0xee, 0x3e, 0x9c, 0x7a, 0x9e, 0x8e, 0x01, 0x00};
u8 smg_duan = 0; //数码管段选
u8 smg_wei = 0; //数码管位选
//遥控按键
u8 remote_key = 0;
u8 num1 = 0;
u8 num = 0;
//ADC电压采样
u16 adcx = 0;
u16 adcx1 = 0;
float temp = 0;
//每2ms执行一次,用于扫描显示管
void TIM2_IRQHandler(void)//TIM2中断
{
static u16 led_t = 0;
if (__HAL_TIM_GET_IT_SOURCE(&TIM2_Handler, TIM_IT_UPDATE) != RESET) //检查指定的中断发生与否:TIM2中断源
{
__HAL_TIM_CLEAR_IT(&TIM2_Handler, TIM_IT_UPDATE);//清除TIMx的中断待处理位:TIM2中断源
if (++led_t == 250) //500ms闪烁
{
led_t = 0;
LED0 = !LED0;
}
if (key_event == 2) //RTC时钟
{
switch (smg_wei)
{
case 0:
smg_duan = smg_num[calendar.hour / 10];
break; //时
case 1:
smg_duan = smg_num[calendar.hour % 10];
break;
case 2:
case 5:
smg_duan = 0x02;
break;
case 3:
smg_duan = smg_num[calendar.min / 10];
break; //分
case 4:
smg_duan = smg_num[calendar.min % 10];
break;
case 6:
smg_duan = smg_num[calendar.sec / 10];
break; //秒
case 7:
smg_duan = smg_num[calendar.sec % 10];
break;
}
}
else if (key_event == 3) //红外遥控(在原例程基础上改为输入数字1到20并保存到变量a)
{
switch (remote_key)
{
case 104:
num1 = 0x00;
num = smg_num[1];
a=1;
break; //按键'1'
case 152:
num1 = 0x00;
num = smg_num[2];
a=2;
break; //按键'2'
case 176:
num1 = 0x00;
num = smg_num[3];
a=3;
break; //按键'3'
case 48:
num1 = 0x00;
num = smg_num[4];
a=4;
break; //按键'4'
case 24:
num1 = 0x00;
num = smg_num[5];
a=5;
break; //按键'5'
case 122:
num1 = 0x00;
num = smg_num[6];
a=6;
break; //按键'6'
case 16:
num1 = 0x00;
num = smg_num[7];
a=7;
break; //按键'7'
case 56:
num1 = 0x00;
num = smg_num[8];
a=8;
break; //按键'8'
case 90:
num1 = 0x00;
num = smg_num[9];
a=9;
break; //按键'9'
case 66:
num1 = smg_num[1];
num = smg_num[0];
a=10;
break; //按键'0'
case 82:
num1 = smg_num[1];
num = smg_num[9];
a=19;
break; //按键'DELETE'
case 162:
num1 = smg_num[2];
num = smg_num[0];
a=20;
break;//按键'POWER'
case 98:
num1 = smg_num[1];
num = smg_num[1];
a=11;
break;//按键'UP'
case 226:
num1 = smg_num[1];
num = smg_num[2];
a=12;
break;//按键'ALIENTEK'
case 34:
num1 = smg_num[1];
num = smg_num[3];
a=13;
break;//按键'LEFT'
case 2:
num1 = smg_num[1];
num = smg_num[4];
a=14;
break;//按键'PLAY'
case 194:
num1 = smg_num[1];
num = smg_num[5];
a=15;
break;//按键'RIGHT'
case 224:
num1 = smg_num[1];
num = smg_num[6];
a=16;
break;//按键'VOL-'
case 168:
num1 = smg_num[1];
num = smg_num[7];
a=17;
break;//按键'DOWN'
case 144:
num1 = smg_num[1];
num = smg_num[8];
a=18;
break;//按键'VOL+'
}
switch (smg_wei)
{
case 0:
case 1:
case 2:
case 3:
smg_duan = 0xff;
break;
case 6:
if (num1) smg_duan = num1;
else smg_duan = 0x00;
break;
case 7:
smg_duan = num;
break;
}
}
else if (key_event == 4) //日期显示
{
switch (smg_wei)
{
case 0:
smg_duan = smg_num[calendar.w_year/1000];
break;
case 1:
smg_duan = smg_num[calendar.w_year%1000/100];
break;
case 2:
smg_duan = smg_num[calendar.w_year%100/10];
break;
case 3:
smg_duan = smg_num[calendar.w_year%10];
break;
case 4:
smg_duan = smg_num[calendar.w_month/10];
break;
case 5:
smg_duan = smg_num[calendar.w_month%10];
break;
case 6:
smg_duan = smg_num[calendar.w_date/10];
break; //Ãë
case 7:
smg_duan = smg_num[calendar.w_date%10];
break;
}
}
if ((key_event > 1) && (key_event < 5))
{
LED_Write_Data(smg_duan, smg_wei); //数码管显示
LED_Refresh();//刷新显示
smg_wei++;
if (key_event == 3)
{
if (smg_wei == 4) smg_wei = 6;
}
if (smg_wei > 7) smg_wei = 0;
}
}
}
//开始任务
void start_task(void *pdata)
{
OS_CPU_SR cpu_sr = 0;
pdata = pdata;
msg_key = OSMboxCreate((void *)0); //创建消息邮箱(按键)
OSStatInit(); //初始化统计任务,会延时1秒左右
OS_ENTER_CRITICAL(); //进入临界区(无法被中断打断)
OSTaskCreate(adc_task, (void *)0, (OS_STK *)&ADC_TASK_STK[ADC_STK_SIZE - 1], ADC_TASK_PRIO); //ADC电压采集
OSTaskCreate(leds_task, (void *)0, (OS_STK *)&LEDS_TASK_STK[LEDS_STK_SIZE - 1], LEDS_TASK_PRIO); //LED流水灯
OSTaskCreate(key_task, (void *)0, (OS_STK *)&KEY_TASK_STK[KEY_STK_SIZE - 1], KEY_TASK_PRIO); //按键任务
OSTaskCreate(remote_task, (void *)0, (OS_STK *)&REMOTE_TASK_STK[REMOTE_STK_SIZE - 1], REMOTE_TASK_PRIO); //遥控控制
OSTaskCreate(main_task, (void *)0, (OS_STK *)&MAIN_TASK_STK[MAIN_STK_SIZE - 1], MAIN_TASK_PRIO); //消息邮箱检测任务
OSTaskSuspend(START_TASK_PRIO); //挂起起始任务
OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
}
//ADC检测任务
void adc_task(void *pdata)
{
while (1)
{
if (key_event == 4)
{
adcx = Get_Adc_Average(ADC_CHANNEL_9, 10); //ADC原始值
temp = (float)adcx * (3.3 / 4096); //ADC电压值
adcx1 = temp;
temp -= adcx1;
temp *= 1000;
}
delay_ms(100);
}
}
#define swap16(x) (x&0XFF)<<8|(x&0XFF00)>>8 //高低字节交换宏定义
#define led_time 70 //延时时间(ms)
//根据a的值调节亮度
void leds_task(void *pdata)
{
srand(calendar.sec);
while (1)
{
if (key_event == 1)
{int c=a*50;
for(int b=0;b<1000;b++)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); //LED0亮
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET); //LED1亮
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET); //LED2亮
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_RESET); //LED3亮
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET); //LED4亮
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_RESET); //LED5亮
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET); //LED6亮
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET); //LED7亮
delay_us(c);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); //LED0灭
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET); //LED1灭
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET); //LED2灭
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_SET); //LED3灭
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET); //LED4灭
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET); //LED5灭
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET); //LED6灭
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET); //LED7灭
delay_us(1000-c);
}
}
delay_ms(15);
}
}
//遥控器任务
void remote_task(void *pdata)
{
while (1)
{
if (key_event == 3)
{
remote_key = Remote_Scan();
}
delay_ms(10);
}
}
//主任务
void main_task(void *pdata)
{
u32 key = 0;
u8 err;
u8 i = 0;
u8 oldkey = 1;
__HAL_TIM_ENABLE(&TIM2_Handler);//使能TIM2外设
key = KEY1_PRES;
OSMboxPost(msg_key, (void *)key); //发送消息
while (1)
{
key = (u32)OSMboxPend(msg_key, 10, &err);
if (key) BEEP = 1; //关闭蜂鸣器
switch (key)
{
case KEY0_PRES://LED灯显示
if (oldkey != key)
{
oldkey = KEY0_PRES;
key_event = KEY0_PRES;
OSTaskSuspend(ADC_TASK_PRIO); //挂起ADC任务
OSTaskSuspend(REMOTE_TASK_PRIO); //挂起遥控任务
__HAL_TIM_DISABLE(&TIM2_Handler);//关闭计时器2(数码管显示)
for (i = 0; i < 8; i++)
{
LED_Write_Data(0x00, i); //数码管显示
LED_Refresh();//刷新显示
}
OSTaskResume(LEDS_TASK_PRIO);//恢复流水灯任务
}
break;
case KEY1_PRES://启动RTC时钟显示
if (oldkey != key)
{
oldkey = KEY1_PRES;
key_event = KEY1_PRES;
OSTaskSuspend(ADC_TASK_PRIO); //挂起ADC任务
OSTaskSuspend(REMOTE_TASK_PRIO);//挂起遥控器任务
__HAL_TIM_DISABLE(&TIM3_Handler);//关闭定时器3(遥控器检测)
smg_duan = 0x00;
smg_wei = 0;
OSTaskSuspend(LEDS_TASK_PRIO); //挂起流水灯任务
HAL_GPIO_WritePin(GPIOC, 0xff, GPIO_PIN_SET); //关闭流水灯
__HAL_TIM_ENABLE(&TIM2_Handler);//启动计时器2(数码管显示)
}
break;
case KEY2_PRES://启动遥控器控制
if (oldkey != key)
{
oldkey = KEY2_PRES;
key_event = KEY2_PRES;
OSTaskSuspend(ADC_TASK_PRIO);//挂起ADC任务
OSTaskSuspend(LEDS_TASK_PRIO);//挂起流水灯任务
HAL_GPIO_WritePin(GPIOC, 0xff, GPIO_PIN_SET); //关闭流水灯
__HAL_TIM_ENABLE(&TIM2_Handler);//关闭计时器2(数码管显示)
num1 = 0x00;
num = 0x00;
smg_wei = 0;
__HAL_TIM_ENABLE(&TIM3_Handler);//使能定时器3(遥控器检测)
OSTaskResume(REMOTE_TASK_PRIO);//恢复遥控器任务
}
break;
case WKUP_PRES://启动ADC采集
if (oldkey != key)
{
oldkey = WKUP_PRES;
key_event = WKUP_PRES;
OSTaskSuspend(REMOTE_TASK_PRIO);//挂起遥控器任务
__HAL_TIM_DISABLE(&TIM3_Handler);//关闭定时器3(遥控器检测)
smg_duan = 0x00;
smg_wei = 0;
OSTaskSuspend(LEDS_TASK_PRIO);//挂起流水灯任务
HAL_GPIO_WritePin(GPIOC, 0xff, GPIO_PIN_SET); //关闭流水灯
OSTaskResume(ADC_TASK_PRIO);//恢复ADC任务
__HAL_TIM_ENABLE(&TIM2_Handler);//启动计时器2(数码管显示)
}
break;
}
delay_ms(10);
}
}
//按键扫描任务
void key_task(void *pdata)
{
u8 key;
while (1)
{
key = KEY_Scan(0);
if (key) OSMboxPost(msg_key, (void *)key); //发送消息
delay_ms(5);
}
}
//系统初始化
void system_init(void)
{
u8 error = 0;
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(RCC_PLL_MUL9); //设置时钟,72M
delay_init(72); //初始化延时函数
uart_init(115200); //串口初始化115200
LED_Init(); //初始化LED
KEY_Init(); //初始化按键
BEEP_Init(); //初始化蜂鸣器
mem_init(); //初始化内存池
LED_SMG_Init(); //初始化数码管
Remote_Init(); //红外遥控初始化
Adc_Init(); //ADC初始化
TIM2_Init(19, 7199); //2ms定时显示
printf("ALIENTEK NANO STM32F1 V1\r\n");
printf("Copyright(C) 2018-2028\r\n");
printf("HARDWARE: V2.00 ,SOFTWARE: V1.00\r\n");
printf("CPU:STM32F103RBT6 72Mhz\r\n");
printf("FLASH:128KB SRAM:20KB\r\n");
Norflash_Init(); //SPI初始化
printf("RTC Check...\r\n");
if (RTC_Init()) //RTC时钟初始化
{
printf("RTC Error!\r\n");
LED6 = 0; //提升RTC错误
error = 1;
}
else
{
printf("OK\r\n");
}
AT24CXX_Init(); //IIC初始化
printf("24C02 Check...\r\n");
if (AT24CXX_Check())
{
printf("24C02 Error!\r\n");
LED7 = 0; //提示24C02错误
error = 1;
}
else
{
printf("OK\r\n");
}
}
//主函数
int main(void)
{
system_init(); //系统初始化
OSInit(); //初始化UCOSII
OSTaskCreate(start_task, (void *)0, (OS_STK *)&START_TASK_STK[START_STK_SIZE - 1], START_TASK_PRIO ); //创建起始任务
OSStart(); //OS启动
}