1 概述
1.1 资源概述
开发板:正点原子STM32F103 Nano开发板
CUBEMX版本:1.3.0
MDK版本:5.23
主控芯片型号:STM32F103RBT6
1.2 实现功能
1 本实验开机进入等待红外触发,如过接收到正确的红外信号,则解码,并在数码管上显示;
2 按键1-7分别控制LED1-LED7,电源按键用来打开所有的LED1-LED7,外星人按键用来关闭所有的LED1-LED7;
3 另外将按键判定从定时器中断中分离出来,放在main函数中;
4 使用vol-,开启和关闭声音;
5 使用开发板上的key1按键用来保存声音的配置,保存的数据写入iic中,这样重新上电或者复位后可以使用;
6 LED0用来指示程序的运行状态。
2 硬件相关知识
2.1电路图
采用38译码器和移位寄存器实现。
2.2 字符查询
字符查询,极性是共阴,排列顺序是a-dp
tips
如果我们要实现小数点,有一个捷径,不用重新生成字符,在原来字符上增加一个或0x01(共阴adp方式)的操作,如H.代码为0x6e|0x01
3 程序实现
此程序在正点原子的红外实验程序基础上进行修改,增加了IIC程序,用来保存按键声音的配置。通常在工程中,使用EEPROM来保存配置信息,这样掉电就不会消失。最常用的是各种设置信息的保存。还有一些ADC的校准信息,程序版本信息等,都会保存在IIC中。
实现的逻辑思想
1、进入main程序,读取IIC中声音的配置变量;
2、依据声音配置变量,设置按键声音开还是关;
3、扫描远程遥控器按键,并作出对应的操作;
4、扫描本地按键,如果key1被按下,则写IIC,保存声音配置。
在主程序中,使用了字符串赋值函数strcpy,以及字符串比较函数strcmp,因此在头文件中需要包含头文件string.h,由于对按键赋值使用到了true和false,因此使用到了bool型变量,需要包含头文件stdbool.h。
程序进行了改写,将定时器中断中的按键检测挪到了主函数中,中断中不宜进行太多的逻辑操作。
程序中增加了一个250ms翻转一次的LED灯,用来当做“心跳”,当程序卡死或者异常时,此灯的状态会表现异常,这也是一种很常见的工程方法。
参数保存还有优化的空间,最佳的方式是在下电过程中进行保存,而不是人工保存,这样能减少EEPROM的写入次数,延长EEPROM的寿命,通常EEPROM的寿命只有几千次。
1,主程序代码如下
- #include "sys.h"
- #include "delay.h"
- #include "usart.h"
- #include "led.h"
- #include "smg.h"
- #include "remote.h"
- #include "timer.h"
- #include "beep.h"
- #include <stdbool.h>
- #include "24cxx.h"
- #include "myiic.h"
- #include "key.h"
- #include <string.h>
- // 共阴数字数组
- // 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 keyRemote=0,keyLocal = 0;; //按键值
- u8 num=0x00;//数值
- u8 num1=0x00;//数值
- u8 smg_wei=6;//数码管位选
- u8 smg_duan=0;//数码管段选
- u8 smg_flag=0;//数码管显示标志 0:正常显示 1:消除鬼影
- u8 t=0;
- char TEXT_Buffer[]={"NANO STM32 IIC TEST"};
- #define SIZE sizeof(TEXT_Buffer)
-
- int main(void)
- {
- bool volState = false ;//true为关闭声音,false为打开声音
- char datatemp[SIZE];
-
- HAL_Init(); //初始化HAL库
- Stm32_Clock_Init(RCC_PLL_MUL9); //设置时钟,72M
- delay_init(72); //初始化延时函数
- uart_init(115200); //串口初始化为115200
- LED_Init(); //初始化与LED连接的硬件接口
- BEEP_Init(); //蜂鸣器初始化
- LED_Init(); //初始化与LED连接的硬件接口
- LED_SMG_Init(); //数码管初始化
- TIM4_Init(19,7199); //数码管2ms定时显示
- Remote_Init(); //红外接收初始化
- AT24CXX_Init(); //IIC初始化
- KEY_Init(); //按键初始化
- if(AT24CXX_Check())//检测不到24c02
- {
- printf("24C02 Check Failed!\r\n");
- delay_ms(500);
- printf("Please Check!\r\n");
- delay_ms(500);
- LED0=!LED0;//DS0闪烁
- }
- else
- printf("24C02 Ready!\r\n");
- printf("WK_UP:save the volume setting!\r\n");//显示提示信息
- printf("1-7:led1-LED7 switch\r\n");
- printf("power:all led off\r\n");
- printf("alientec:all led on\r\n");
- printf("vol-:sound switch\r\n");
- AT24CXX_Read(0,datatemp,SIZE);
- printf("The Data Readed Is:\r\n");//提示传送完成
- printf("%s\r\n",datatemp);//显示读到的字符串
- if(strcmp(datatemp,"true"))
- volState = false ;
- else
- volState = true ;
-
- while(1)
- {
- keyRemote = Remote_Scan();
- if(keyRemote)
- {
- switch(keyRemote)
- {
- case 104:
- num1=0x00; num = smg_num[1]; BEEP=volState;
- HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_1);
- break; //按键'1'
- case 152:
- num1=0x00;num=smg_num[2];BEEP = volState;
- HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_2);
- break; //按键'2'
- case 176:
- num1=0x00;num=smg_num[3];BEEP = volState;
- HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_3);
- break; //按键'3'
- case 48:
- num1=0x00;num=smg_num[4];BEEP = volState;
- HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_4);
- break; //按键'4'
- case 24:
- num1=0x00;num=smg_num[5];BEEP = volState;
- HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_5);
- break; //按键'5'
- case 122:
- num1=0x00;num=smg_num[6];BEEP = volState;
- HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_6);
- break; //按键'6'
- case 16:
- num1=0x00;num=smg_num[7];BEEP = volState;
- HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_7);
- break; //按键'7'
- case 56:num1=0x00;num=smg_num[8];BEEP = volState;break; //按键'8'
- case 90:num1=0x00;num=smg_num[9];BEEP = volState;break; //按键'9'
- case 66:num1=0x00;num=smg_num[0];BEEP = volState;break; //按键'0'
- case 82:num1=0x00;num=smg_num[17];BEEP = volState;break; //按键'DELETE'
- case 162:
- num1=smg_num[1];num=smg_num[0];BEEP = volState;
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|
- GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7,GPIO_PIN_SET); //PC0~7置1,灯灭
- break;//按键'POWER'
- case 98:num1=smg_num[1];num=smg_num[1];BEEP = volState; break;//按键'UP'
- case 226:
- num1=smg_num[1];num=smg_num[2];BEEP = volState;
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|
- GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7,GPIO_PIN_RESET); //PC0~7置0,灯开
- break;//按键'ALIENTEK'
- case 34:num1=smg_num[1];num=smg_num[3];BEEP = volState; break;//按键'LEFT'
- case 2:num1=smg_num[1];num=smg_num[4];BEEP = volState; break;//按键'PLAY'
- case 194:num1=smg_num[1];num=smg_num[5];BEEP = volState; break;//按键'RIGHT'
- case 224:
- num1=smg_num[1];num=smg_num[6];BEEP = 0;
- volState = !volState;
- break;//按键'VOL-'
- case 168:num1=smg_num[1];num=smg_num[7];BEEP = volState; break;//按键'DOWN'
- case 144:num1=smg_num[1];num=smg_num[8];BEEP = volState; break;//按键'VOL+'
- }
- }else
- {
- BEEP=1;
- }
- if(volState)
- strcpy(TEXT_Buffer,"true");
- else
- strcpy(TEXT_Buffer,"false");
-
- keyLocal=KEY_Scan(0);
- if(keyLocal==WKUP_PRES)//WK_UP 按下,写入24C02
- {
- printf("\r\nStart Write 24C02....\r\n");
- AT24CXX_Write(0,(u8*)TEXT_Buffer,SIZE);
- printf("24C02 Write Finished!\r\n");//提示传送完成
- printf("\r\nStart Read 24C02....\r\n");
- AT24CXX_Read(0,datatemp,SIZE);
- printf("The Data Readed Is:\r\n");//提示传送完成
- printf("%s\r\n",datatemp);//显示读到的字符串
- }
-
- HAL_Delay(1);
- t++;
- if(t==250)//LED0每500MS闪烁
- {
- t=0;
- LED0=!LED0;
- }
- }
- }
- //定时器4中断服务函数调用
- void TIM4_IRQHandler(void)
- {
- if(__HAL_TIM_GET_IT_SOURCE(&TIM4_Handler, TIM_IT_UPDATE) !=RESET)
- {
- __HAL_TIM_CLEAR_IT(&TIM4_Handler, TIM_IT_UPDATE);
- }
- if(smg_wei==6)//数码管位
- {
- smg_duan = num1;
- }
- else if(smg_wei==7)
- {
- smg_duan = num;
- }
- if(smg_flag)
- LED_Write_Data(0x00,smg_wei);//消除鬼影(段码不显示)
- else
- LED_Write_Data(smg_duan,smg_wei);//正常显示
- LED_Refresh();//数码管数据更新
- smg_flag=!smg_flag;
- if(smg_flag==0)//正常显示才更新位码
- {
- smg_wei++;
- if(smg_wei==8) smg_wei=6;
- }
- }
复制代码
4 实验结果
实验结果如下,所有逻辑操作正确
串口显示信息,声音按键设置可以正常保存,复位或者断电重启后并不会消失。
5 额外的TIPS
调整LED亮度的几种方式
1,电路方法:减小限流电阻阻值,从而增大LED的电流,达到增加亮度目的。
2,软件方法:增加LED在单位时间内的总亮时长,方式有两种,增加刷新频率以及增大单个刷新周期内的点亮时间。
3,物理方法:如果LED有透光保护膜,增加透光膜的透明度。
|