一、题目内容分析
二、LCD单字符高亮显示实现
本次要求显示两个字符,此函数高亮pos及它后面一个字符
void highlight(uint8_t *str,uint8_t pos)
{
int i = 0;
for(i = 0; i <= 20; i++)
{
if(i != pos && i!= (pos+1))
LCD_DisplayChar(Line3,(320 - (16 * i)),str[i]);
}
LCD_SetBackColor(Yellow);
LCD_DisplayChar(Line3,(320 - (16 * pos)),str[pos]);
LCD_SetBackColor(Yellow);
LCD_DisplayChar(Line3,(320 - (16 * (pos+1))),str[pos+1]);
LCD_SetBackColor(Black);
}
三、EEPROM
我们主要编写这两个函数
//字节写函数
void at24c02_Byte_Write(unsigned char addr,unsigned char cSendByte);
//随机读
unsigned char at24c02_Byte_read(unsigned char addr);
找到竞赛平台里的资料
字节写:
- 起始信号
- 器件地址————读为低电平 -> 0xa0
- 等待应答
- 发送字节地址
- 等待应答
- 发送数据
- 等待应答
- 结束信号
//字节写函数
void at24c02_Byte_Write(unsigned char addr,unsigned char cSendByte)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(cSendByte);
I2CWaitAck();
I2CStop();
}
随机读时序
- 开始信号
- 器件地址写——0xa0
- 等待应答
- 发送字节地址
- 等待应答
- 器件地址读——0xa1
- 等待应答
- 接收字节
- 发送无应答
- 结束信号
//随机读
unsigned char at24c02_Byte_read(unsigned char addr)
{
unsigned char dat;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
dat = I2CReceiveByte();
I2CSendNotAck();
I2CStop();
return dat;
}
四、usr.c
#include "usr.h"
/* values ------------------------------------------------------------------*/
char time_state = Runing;
struct keys key[4] = {0,0,0,0};
uint8_t storage_location = 1;
uint8_t hour = 1,min = 2,sec = 10;
char timer_run_flag = 0;
int hightlight_sel = -1;
unsigned char read_data = 0;
void read_initial_data(void){
hour = at24c02_Byte_read(1);
min = at24c02_Byte_read(2);
sec = at24c02_Byte_read(3);
}
//led
void led_set(uint8_t display)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,display<<8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
//lcd
void display_init(void)
{
LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
led_set(0x00);
}
void highlight(uint8_t *str,uint8_t pos)
{
int i = 0;
for(i = 0; i <= 20; i++)
{
if(i != pos && i!= (pos+1))
LCD_DisplayChar(Line3,(320 - (16 * i)),str[i]);
}
LCD_SetBackColor(Yellow);
LCD_DisplayChar(Line3,(320 - (16 * pos)),str[pos]);
LCD_SetBackColor(Yellow);
LCD_DisplayChar(Line3,(320 - (16 * (pos+1))),str[pos+1]);
LCD_SetBackColor(Black);
}
//pwm开始输出
void pwm_out_start(void)
{
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
}
//pwm停止输出
void pwm_out_off(void)
{
HAL_TIM_PWM_Stop(&htim3,TIM_CHANNEL_1);
}
void menu_display(void)
{
if(time_state!=Runing){
led_set(0x00);
pwm_out_off();
}
if(timer_run_flag == 1){
time_state = Runing;
pwm_out_start();
}else if(timer_run_flag == 0){
time_state = Pause;
}else if(timer_run_flag == 2){
time_state = Standby;
}else{
time_state = Setting;
}
char text[30];
sprintf(text," No %d ",storage_location);
LCD_DisplayStringLine(Line1,(u8*)text);
if(min < 10 && hour <10 && sec<10){ // 0 0 0
sprintf(text," 0%d:0%d:0%d ",hour,min,sec);
}else if(hour <10 && min < 10 && sec >= 10){ // 0 0 1
sprintf(text," 0%d:0%d:%2d ",hour,min,sec);
}else if(hour <10 && min >= 10 && sec < 10){ // 0 1 0
sprintf(text," 0%d:%2d:0%d ",hour,min,sec);
}else if(hour <10 && min >= 10 && sec >= 10){ // 0 1 1
sprintf(text," 0%d:%2d:%2d ",hour,min,sec);
}else if(hour >= 10 && min < 10 && sec < 10){ // 1 0 0
sprintf(text," %2d:0%d:0%d ",hour,min,sec);
}else if(hour >= 10 && min < 10 && sec >= 10){ // 1 0 1
sprintf(text," %2d:0%d:%2d ",hour,min,sec);
}else if(hour >= 10 && min >= 10 && sec < 10){ // 1 1 0
sprintf(text," %2d:%2d:0%d ",hour,min,sec);
}else if(hour >= 10 && min >= 10 && sec >= 10){ // 1 1 1
sprintf(text," %2d:%2d:%2d ",hour,min,sec);
}
if(time_state == Setting){
if(hightlight_sel == hightlight_sel_1){
highlight((u8*)text,Hightlight_location1);
}else if(hightlight_sel == hightlight_sel_2){
highlight((u8*)text,Hightlight_location2);
}else if(hightlight_sel == hightlight_sel_3){
highlight((u8*)text,Hightlight_location3);
}
}else{
LCD_DisplayStringLine(Line3,(u8*)text);
}
if(time_state == Runing){
sprintf(text," Running ");
}else if(time_state == Standby){
sprintf(text," Standby ");
}else if(time_state == Setting){
sprintf(text," Setting ");
}else if(time_state == Pause){
sprintf(text," Pause ");
}
LCD_DisplayStringLine(Line6,(u8*)text);
}
void timer_cnt(void){
if(sec == 0){
sec = 60;
min --;
if(min == 0){
min = 59;
hour --;
if(hour == 0){
hour = 0;
}
}
}
}
void key_control(void){
//短按
if(key[0].key_short_flag == 1){
//read_data = at24c02_Byte_read(1);
key[0].key_short_flag = 0;
storage_location ++;
if(storage_location > No_5){storage_location = No_1;}
}else if(key[1].key_short_flag == 1){
key[1].key_short_flag = 0;
timer_run_flag = 3;
time_state = Setting;
if(time_state == Setting){
hightlight_sel++;
hightlight_sel %= 3;
}
}else if(key[2].key_short_flag == 1){
key[2].key_short_flag = 0;
//数字增加
if(time_state == Setting){
if(hightlight_sel == hightlight_sel_1){
hour ++;
hour %= 60;
}else if(hightlight_sel == hightlight_sel_2){
min ++;
min %= 60;
}else {
sec ++;
sec %= 60;
}
}
}else if(key[3].key_short_flag == 1){
key[3].key_short_flag = 0;
// at24c02_Byte_Write(1,2);
// HAL_Delay(5);
// at24c02_Byte_Write(2,39);
// HAL_Delay(5);
// at24c02_Byte_Write(3,11);
if(time_state == Setting){
HAL_TIM_Base_Start_IT(&htim7);
timer_run_flag = 1;
}else if(time_state == Standby){ //取消定时器运行
HAL_TIM_Base_Stop_IT(&htim7);
timer_run_flag = 0;
}else{
//定时器启动
if(timer_run_flag == 0){
HAL_TIM_Base_Start_IT(&htim7);
timer_run_flag = 1;
}else if(timer_run_flag == 1){
//定时器暂停
HAL_TIM_Base_Stop_IT(&htim7);
timer_run_flag = 0;
}
}
}
//长按
if(key[0].key_long_flag == 1){
key[0].key_long_flag = 0;
}else if(key[1].key_long_flag == 1){
key[1].key_long_flag = 0;
if(time_state == Setting){
at24c02_Byte_Write(storage_location*3-2,hour);
HAL_Delay(5);
at24c02_Byte_Write(storage_location*3-1,min);
HAL_Delay(5);
at24c02_Byte_Write(storage_location*3 ,sec);
HAL_Delay(5);
}
}else if(key[2].key_long_flag == 1){
// key[2].key_long_flag = 0;
if(time_state == Setting){
if(hightlight_sel == hightlight_sel_1){
hour ++;
hour %= 60;
}else if(hightlight_sel == hightlight_sel_2){
min ++;
min %= 60;
}else {
sec ++;
sec %= 60;
}
if(key[2].key_sta == 1){
key[2].key_long_flag = 0;
}
}
}else if(key[3].key_long_flag == 1){
key[3].key_long_flag = 0;
//长按取消定时器运行,回到Standby状态
// if(timer_run_flag == 1){
timer_run_flag = 2;
// }
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim -> Instance == TIM6){
key[0].key_sta = HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin);
key[1].key_sta = HAL_GPIO_ReadPin(B2_GPIO_Port,B2_Pin);
key[2].key_sta = HAL_GPIO_ReadPin(B3_GPIO_Port,B3_Pin);
key[3].key_sta = HAL_GPIO_ReadPin(B4_GPIO_Port,B4_Pin);
for(uint8_t i = 0;i < 4;i++){
switch(key[i].key_judge){
case 0:{
if(key[i].key_sta == 0){
key[i].key_judge = 1;
}else{
key[i].key_judge = 0;
}
}break;
case 1:{
if(key[i].key_sta == 0){
key[i].key_judge = 2;
}else{
key[i].key_judge = 0;
}
}break;
case 2:{
if(key[i].key_sta == 1){
if(key[i].key_time <= Key_shorttime){
key[i].key_short_flag = 1;
key[i].key_time = 0;
key[i].key_judge = 0;
}
}else{
if(key[i].key_time >= Key_longtime){
key[i].key_time = 0;
key[i].key_long_flag = 1;
key[i].key_judge = 0;
}
key[i].key_time ++;
}
}break;
}
}
}
if(htim -> Instance == TIM7){ //倒计时计时器
if(timer_run_flag == 1){
timer_cnt();
sec --;
}
}
if(htim -> Instance == TIM17){ //led闪烁定时器
static uint8_t cnt = 0;
if(timer_run_flag == 1){
if(cnt<5){
led_set(0x01);
}else{
led_set(0x00);
}
cnt++;
cnt %= 10;
}
else{
cnt = 0;
}
}
}
五、usr.h
#ifndef __USR_H
#define __USR_H
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "lcd.h"
#include "tim.h"
#include "stdio.h"
#include "i2c_hal.h"
/* defines -------------------------------------------------------------------*/
#define Runing 0
#define Setting 1
#define Standby 2
#define Pause 3
#define No_1 1 //1-3
#define No_2 2 //4-6
#define No_3 3 //7-9
#define No_4 4 //10-12
#define No_5 5 //13-15
#define Key_longtime 80
#define Key_shorttime 30
#define Hightlight_location1 7
#define Hightlight_location2 10
#define Hightlight_location3 13
#define hightlight_sel_1 0
#define hightlight_sel_2 1
#define hightlight_sel_3 2
/* structs -------------------------------------------------------------------*/
struct keys{
uint8_t key_sta;
uint8_t key_judge;
uint8_t key_short_flag;
uint8_t key_long_flag;
uint16_t key_time;
};
void display_init(void);
void menu_display(void);
void key_control(void);
void timer_cnt(void);
void read_initial_data(void);
#endif
六、总结
I2C的两个引脚不需要额外配置(在cubemx配置)
记得调用"i2c_hal.c"里提供的I2CInit()
cubemx在配置定时器的时候记得开启中断,在while前启动