CubeMX配置
代码:
/*定义时间日期结构体变量*/
RTC_TimeTypeDef rtcTime; /*存储时间结构体变量*/
RTC_DateTypeDef rtcDate; /*存储日期结构体变量*/
HAL_RTC_GetTime(&hrtc,&rtcTime,FORMAT_BIN); /*更新时间*/
HAL_RTC_GetDate(&hrtc,&rtcDate,FORMAT_BIN); /*更新日期*/
LCD_SetTextColor(Black);
LCD_SetBackColor(White);
LCD_DisplayStringLine(Line1,(uint8_t *)" Data ");
/*显示日期*/
sprintf(text," date:20%d-%02d-%02d ",rtcDate.Year,rtcDate.Month,rtcDate.Date);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
/*显示时间*/
sprintf(text," time:%02d:%02d:%02d ",rtcTime.Hours,rtcTime.Minutes,rtcTime.Seconds);
LCD_DisplayStringLine(Line5,(uint8_t *)text);
/*---------------------------------------------------------------*/
rtcDate.Year=24;
rtcDate.Month=12;
rtcDate.Date=31;
rtcTime.Hours=23;
rtcTime.Minutes=59;
rtcTime.Seconds=50;
HAL_RTC_SetDate(&hrtc, &rtcDate, RTC_FORMAT_BIN); /*写入时间*/
HAL_RTC_SetTime(&hrtc, &rtcTime, RTC_FORMAT_BIN); /*写入日期*/
/*---------------------------------------------------------------*/
测试代码
#include "app.h"
#include "lcd.h"
#include "stdio.h"
#include "dma.h"
#include "tim.h"
#include "usart.h"
#include "stdbool.h" /*包含布尔类型定义*/
#include <stdio.h>
#include "math.h"
#include "adc.h"
#include "dac.h"
#include "rtc.h"
/********************************************************************************************/
uint8_t dis=0; /*利用这个标志,上电之后运行完对应的初始化后*/
/********************************************************************************************/
/********************************************************************************************/
Key keys[4]={0,0,0,0,0}; /*按键的结构体变量初始化*/
/********************************************************************************************/
/********************************************************************************************/
char text[30]; /*用来存放转换后的变量*/
/********************************************************************************************/
/********************************************************************************************/
//USART 串口相关的全局变量
uint8_t usart1_rx_buffer[USART_DMA_RX_BUFFER_MAXIMUM]; //串口1的DMA接收缓冲区
uint8_t usart1_rx_flag = 0; //DMA接收成功标志 0:未接收到 1:接收到等待处理
uint16_t usart1_rx_len = 0; //DMA一次空闲中断接收到的数据长度
/*******************************************************************************************/
/*******************************************************************************************/
//FRQ 输入捕获相关的全局变量
uint8_t testFinish=0; /*捕获完成标志*/
uint8_t testFinish2=0; /*捕获完成标志*/
uint16_t J10_Frq=0,J9_Frq=0; /*捕获后转换的测量频率,J9\J10是连接的跳帽*/
float J10_Duty=0,J9_Duty=0; /*捕获后转换的占空比,J9\J10是连接的跳帽*/
/*******************************************************************************************/
/*******************************************************************************************/
/*定义时间日期结构体变量*/
RTC_TimeTypeDef rtcTime; /*存储时间结构体变量*/
RTC_DateTypeDef rtcDate; /*存储日期结构体变量*/
/*******************************************************************************************/
/*-------------------------------------------------------------------------------------
* 函数名称:Main_App
* 函数功能:放在主函数的while(1)循环里,这样以后生成就不用动其他文件了。直接在这里操作
---------------------------------------------------------------------------------------*/
void Main_App(void) /*主函数while(1)*/
{
if(dis) /*循环的业务代码放这里*/
{
HAL_RTC_GetTime(&hrtc,&rtcTime,FORMAT_BIN); /*更新时间*/
HAL_RTC_GetDate(&hrtc,&rtcDate,FORMAT_BIN); /*更新日期*/
LCD_SetTextColor(Black);
LCD_SetBackColor(White);
LCD_DisplayStringLine(Line1,(uint8_t *)" Data ");
/*显示日期*/
sprintf(text," date:20%d-%02d-%02d ",rtcDate.Year,rtcDate.Month,rtcDate.Date);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
/*显示时间*/
sprintf(text," time:%02d:%02d:%02d ",rtcTime.Hours,rtcTime.Minutes,rtcTime.Seconds);
LCD_DisplayStringLine(Line5,(uint8_t *)text);
}
else /*只进来一次,放外设的初始化*/
{
Led_PIN_SET();
LCD_Init();
LCD_Clear(White);
/*---------------------------------------------------------------*/
rtcDate.Year=24;
rtcDate.Month=12;
rtcDate.Date=31;
rtcTime.Hours=23;
rtcTime.Minutes=59;
rtcTime.Seconds=50;
HAL_RTC_SetDate(&hrtc, &rtcDate, RTC_FORMAT_BIN); /*写入时间*/
HAL_RTC_SetTime(&hrtc, &rtcTime, RTC_FORMAT_BIN); /*写入日期*/
/*---------------------------------------------------------------*/
dis=1;
}
}
/***********************************************************************************************************************
RTC BEGIN
**********************************************************************************************************************/
/*定义时间日期结构体变量*/
//RTC_TimeTypeDef rtcTime; /*存储时间结构体变量*/
//RTC_DateTypeDef rtcDate; /*存储日期结构体变量*/
//读取时间
//HAL_RTC_GetTime(&hrtc,&rtcTime,FORMAT_BIN); /*更新时间*/
//HAL_RTC_GetDate(&hrtc,&rtcDate,FORMAT_BIN); /*更新日期*/
//写入新时间
//rtcDate.Year=24;
//rtcDate.Month=12;
//rtcDate.Date=31;
//rtcTime.Hours=23;
//rtcTime.Minutes=59;
//rtcTime.Seconds=50;
//HAL_RTC_SetDate(&hrtc, &rtcDate, RTC_FORMAT_BIN); /*写入时间*/
//HAL_RTC_SetTime(&hrtc, &rtcTime, RTC_FORMAT_BIN); /*写入日期*/
/***********************************************************************************************************************
RTC BEGIN
**********************************************************************************************************************/
/***********************************************************************************************************************
DAC BEGIN
**********************************************************************************************************************/
//HAL_DAC_Start(&hdac1,DAC_CHANNEL_1); /*开启dac通道一*/
//HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1,DAC_ALIGN_12B_R, (4095*M_T.Volt/3.3f));/*DAC,赋初值*/
/***********************************************************************************************************************
DAC BEGIN
**********************************************************************************************************************/
/***********************************************************************************************************************
ADC BEGIN
**********************************************************************************************************************/
double Get_ADValue(ADC_HandleTypeDef *Pin)
{
uint16_t ad_val=0;
HAL_ADC_Start(Pin);
ad_val=HAL_ADC_GetValue(Pin);
//HAL_ADC_Stop(Pin);
return ad_val*3.3/4096;
}
/***********************************************************************************************************************
ADC END
**********************************************************************************************************************/
/***********************************************************************************************************************
PWM BEGIN
**********************************************************************************************************************/
/*设置对应的频率和占空比输出*/
//公式:频率=80 000 000 / PSC / ARR 需要配置PSC ARR
//占空比(%) = CCR1 / (ARR+1)
//__HAL_TIM_SET_COMPARE(&htim17,TIM_CHANNEL_1,CCR1); /*把传参进来的PWM值送给定时的channe1通道*/
void Set_PWM(uint16_t Freq,uint16_t Duty)
{
uint32_t PSCArr,psc,arr; //PSCArr=psc*arr
PSCArr = 80000000/Freq;
psc=sqrt(PSCArr); /*开方,需要包含math.h*/
arr = PSCArr/psc;
HAL_TIM_PWM_Stop(&htim17,TIM_CHANNEL_1); /*停止PWM输出*/
TIM17->PSC=psc-1; /*分频系数*/
TIM17->ARR=arr-1; /*计数值*/
TIM17->CCR1=Duty/100.0*arr; /*占空比*/
HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);/*重新开启PWM*/
}
/***********************************************************************************************************************
PWM BEGIN
**********************************************************************************************************************/
/***********************************************************************************************************************
FRQ BEGIN
**********************************************************************************************************************/
/*定时器输入捕获中断回调*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
static uint16_t cycle=0,cycle2=0; /*捕获的电平周期计数*/
static float dutyCnt=0,dutyCnt2=0; /*捕获的占空比计数*/
if(htim==&htim3) /*J9口*/
{
if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_2) //占空比计数值
{
dutyCnt2=TIM3->CCR2;
}
else if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1) //周期计数值
{
cycle2=TIM3->CCR1;
J9_Frq=1000000/cycle2; //转换成频率,因为分频系数设成了80,所以这里是1 000 000Hz,
J9_Duty=100*dutyCnt2/cycle2; //占空比
testFinish=1;
}
}
else if(htim==&htim2)
{
dutyCnt=TIM2->CCR2;
cycle=TIM2->CCR1;
J10_Frq=1000000/cycle; //频率
J10_Duty=100*dutyCnt/cycle; //占空比
testFinish2=1;
}
}
/***********************************************************************************************************************
FRQ END
**********************************************************************************************************************/
/***********************************************************************************************************************
USART BEGIN
**********************************************************************************************************************/
/*printf函数重定义*/
int fputc(int ch,FILE *f)
{
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,10);
return ch;
}
/*串口中断回调函数*/
void My_UARTEx_RxEventCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) //如果是串口1
{
usart1_rx_len = USART_DMA_RX_BUFFER_MAXIMUM - (__HAL_DMA_GET_COUNTER(&hdma_usart1_rx)); //接收个数等于接收缓冲区总大小减剩余计数
usart1_rx_buffer[usart1_rx_len] ='\0'; //清除上次缓存的数据
if(usart1_rx_len!=0)
usart1_rx_flag = 1; //标志已经成功接收到一包等待处理
HAL_UART_Receive_DMA(&huart1,usart1_rx_buffer,USART_DMA_RX_BUFFER_MAXIMUM); //启动DMA接收,UART1_RX_BUF:数据接收缓冲
}
}
/***********************************************************************************************************************
USART END
**********************************************************************************************************************/
/***********************************************************************************************************************
KEY BEGIN
**********************************************************************************************************************/
/*----------------------------------------------------------------------------------------------------
*函数名称:KEY_Scan(uint8_t mode)
*函数功能:按键处理函数,状态机,假设同时只有一个按键按下,无论长按还是短按都只判断按下,记作一次
这个代码只能一次性判断一个按键按下,无法对同一时刻多个按键按下进行判断
*输 入:mode 1:按键连按; 2:按键只读取一次
*返 回 值:按键键值
-----------------------------------------------------------------------------------------------------*/
uint8_t KEY_Scan(void)
{
static uint8_t key_up=1;//按键按松开的标志
if(key_up && (B1==0 || B2==0 || B3==0 || B4==0)) //检测到有按键按下
{
HAL_Delay(10);//去抖动
key_up=0;
if(B1==0) return 1; //1
else if(B2==0) return 2; //2
else if(B3==0) return 3; //3
else if(B4==0) return 4; //4
}
else if(B1==1 && B2==1 && B3==1 && B4==1) key_up=1;
return 0;// 没有按键按下
}
/*这里放在定时器中断里*/
/*----------------------------------------------------------------------------------------------------
*函数名称:void key_scan(void)e)
*函数功能:按键处理函数,支持长按(keys[i].sflag =1)
*输 入:
*返 回 值:
*修 改 人:ZXP 2023/12/27
-----------------------------------------------------------------------------------------------------*/
void key_scan(void)
{
static uint8_t i=0;
/*按键状态读取*/
keys[0].state = B1;
keys[1].state = B2;
keys[2].state = B3;
keys[3].state = B4;
/*支持多个按键同时按下*/
for(i=0;i<4;i++)
{
switch(keys[i].keystate) /*用来消抖的,定时器6是每10ms进来一次,第一次进来这个为0,2次进来才开读取按键键值始*/
{
case 0:
if( !keys[i].state)
{
keys[i].keystate =1; /*10ms后进入case 1*/
keys[i].keytime = 0;
}
break;
case 1:
if(!keys[i].state)
{
keys[i].keystate =2; /*10ms后进入case 2*/
}
else
keys[i].keystate = 0; /*表示没有按键按下,消抖了*/
break;
case 2:
if(!keys[i].state) /*松手检测,这里表示没有松手*/
{
// if(keys[i].keytime < 1000) /*小于800才加,避免溢出然后置零*/
keys[i].keytime+=10; /*按键按下的时间累加,一次10ms*/
if(keys[i].keytime > 800) /*800ms*/
{
keys[i].lflag = 1; /*表示长按*/
// keys[i].sflag = 0; /*短按清零*/
}
}
else /*表示松手了*/
{
if (keys[i].keytime <= 800)
{
keys[i].sflag = 1; /*表示短按*/
keys[i].lflag = 0; /*功能函数里来判断这两个变量状态*/
}
keys[i].keytime = 0; /**/
keys[i].keystate = 0;
keys[i].lflag = 0; /*长按松开清零,短按功能函数里清零*/
}
break;
default:
break;
}
}
}
/***********************************************************************************************************************
KEY END
**********************************************************************************************************************/
/***********************************************************************************************************************
TIME BEGIN
**********************************************************************************************************************/
/*中断回调函数*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/*定时器6*/
if(htim->Instance==TIM6)
{
key_scan();
}
}
/***********************************************************************************************************************
TIME END
**********************************************************************************************************************/
/***********************************************************************************************************************
LCD BEGIN
**********************************************************************************************************************/
void My_LCD_DisplayStringLine(uint8_t Line, uint16_t Column,uint8_t *ptr) /*自己修改的字符串显示*/
{
u16 refcolumn = Column;//319;
while ((*ptr != 0)) //20
{
LCD_DisplayChar(Line, refcolumn, *ptr);
refcolumn -= 16;
ptr++;
}
}
//举例
//char text[30]; /*用来存放转换后的变量*/
//LCD_SetTextColor(Black);
//LCD_SetBackColor(White);
//LCD_DisplayStringLine(Line1,(uint8_t *)" Data ");
///*显示日期*/
//sprintf(text," date:20%d-%02d-%02d ",rtcDate.Year,rtcDate.Month,rtcDate.Date);
//LCD_DisplayStringLine(Line3,(uint8_t *)text);
///*显示时间*/
//sprintf(text," time:%02d:%02d:%02d ",rtcTime.Hours,rtcTime.Minutes,rtcTime.Seconds);
//LCD_DisplayStringLine(Line5,(uint8_t *)text);
/***********************************************************************************************************************
LCD END
**********************************************************************************************************************/
/***********************************************************************************************************************
LED BEGIN
************************************************************************************************************************/
uint16_t GPIOC_ODR=0xFF00; //两个FF对应的高位PC8~15
/*----------------------------------------------------------------------------------------------------
*函数名称:Led_PIN_SET()
*函数功能:流水灯全部置高电平
*输 入:无
*返 回 值:无
-----------------------------------------------------------------------------------------------------*/
void Led_PIN_SET(void)
{
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,0xff<<8,GPIO_PIN_SET);
GPIOC_ODR=GPIOC->ODR; //记录本次流水灯的点亮状态
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
/*----------------------------------------------------------------------------------------------------
*函数名称:LedCtrl(uint8_t ds,uint8_t LED_State)
*函数功能:点亮和熄灭指定的LED灯
*输 入:ds:1~8,LED的位置,LED_State:0/1;0:指定的灯熄灭,1:指定的灯点亮
*返 回 值:无
*修 改 人:ZXP 2023/12/28 10:41
-----------------------------------------------------------------------------------------------------*/
void LedCtrl(uint8_t ds,uint8_t LED_State)
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);//开启锁存器的数据直通
if(LED_State)
{
GPIOC->ODR |=0xFF00; //熄灭所有led
GPIOC->ODR &= ~(1<<(ds+7) | ~GPIOC_ODR); //保持上一个灯的状态,加7是为了移到高8位
GPIOC_ODR=GPIOC->ODR; //记录本次流水灯的点亮状态
}
else if(!LED_State)
{
GPIOC->ODR |= (1<<(ds+7) | GPIOC_ODR); //熄灭指定的灯,或运算,1,加7是为了移到高8位
GPIOC_ODR=GPIOC->ODR; //记录本次流水灯的点亮状态
}
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);//锁存
}
/***********************************************************************************************************************
LED END
************************************************************************************************************************/