镜子里的屏幕之三:软件设计
在上个帖子里,已经使用STM32CubeMX软件搭建了软件的框架,现在就来编写代码实现我们需要的功能。
镜子里的屏幕这个项目使用到的硬件设备有显示、RTC、MPU6050、按键等。下面分别进行软件的编写。
首先是显示部分,我使用的是7段LED显示器,扫描显示,只要把显示数据送到控制端口,再分别选通位选线就可以了。具体的端口分配见 镜子里的屏幕之一:电路设计,这里不再赘述。具体代码如下:
一、显示部分:
宏定义
/* 关闭LED显示,清除段选择 */
#define NUM_X do{ \
HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_B_Pin|SEG_7_C_Pin|SEG_7_D_Pin|SEG_7_E_Pin|SEG_7_F_Pin|SEG_7_G_Pin|SEG_7_dp_Pin, GPIO_PIN_RESET); \
HAL_GPIO_WritePin(GPIOC, Hour_Shiwei_Pin|Hour_Gewei_Pin|Min_Shiwei_Pin|Min_Gewei_Pin|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET); \
} while(0)
/* 显示 0..9 */
#define NUM_0 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_B_Pin|SEG_7_C_Pin|SEG_7_D_Pin|SEG_7_E_Pin|SEG_7_F_Pin, GPIO_PIN_SET); } while(0)
#define NUM_1 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_B_Pin|SEG_7_C_Pin, GPIO_PIN_SET); } while(0)
#define NUM_2 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_B_Pin|SEG_7_D_Pin|SEG_7_E_Pin|SEG_7_G_Pin, GPIO_PIN_SET); } while(0)
#define NUM_3 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_B_Pin|SEG_7_C_Pin|SEG_7_D_Pin|SEG_7_G_Pin, GPIO_PIN_SET); } while(0)
#define NUM_4 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_B_Pin|SEG_7_C_Pin|SEG_7_F_Pin|SEG_7_G_Pin, GPIO_PIN_SET); } while(0)
#define NUM_5 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_C_Pin|SEG_7_D_Pin|SEG_7_F_Pin|SEG_7_G_Pin, GPIO_PIN_SET); } while(0)
#define NUM_6 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_C_Pin|SEG_7_D_Pin|SEG_7_E_Pin|SEG_7_F_Pin|SEG_7_G_Pin|SEG_7_dp_Pin, GPIO_PIN_SET); } while(0)
#define NUM_7 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_B_Pin|SEG_7_C_Pin, GPIO_PIN_SET); } while(0)
#define NUM_8 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_B_Pin|SEG_7_C_Pin|SEG_7_D_Pin|SEG_7_E_Pin|SEG_7_F_Pin|SEG_7_G_Pin, GPIO_PIN_SET); } while(0)
#define NUM_9 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_B_Pin|SEG_7_C_Pin|SEG_7_D_Pin|SEG_7_F_Pin|SEG_7_G_Pin, GPIO_PIN_SET); } while(0)
/* 镜像显示 0..9 */
#define NUM_F0 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_B_Pin|SEG_7_C_Pin|SEG_7_D_Pin|SEG_7_E_Pin|SEG_7_F_Pin, GPIO_PIN_SET); } while(0)
#define NUM_F1 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_B_Pin|SEG_7_C_Pin, GPIO_PIN_SET); } while(0)
#define NUM_F2 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_C_Pin|SEG_7_D_Pin|SEG_7_F_Pin|SEG_7_G_Pin, GPIO_PIN_SET); } while(0)
#define NUM_F3 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_B_Pin|SEG_7_C_Pin|SEG_7_D_Pin|SEG_7_G_Pin, GPIO_PIN_SET); } while(0)
#define NUM_F4 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_B_Pin|SEG_7_C_Pin|SEG_7_E_Pin|SEG_7_G_Pin, GPIO_PIN_SET); } while(0)
#define NUM_F5 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_B_Pin|SEG_7_D_Pin|SEG_7_E_Pin|SEG_7_G_Pin, GPIO_PIN_SET); } while(0)
#define NUM_F6 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_B_Pin|SEG_7_D_Pin|SEG_7_E_Pin|SEG_7_F_Pin|SEG_7_G_Pin|SEG_7_dp_Pin, GPIO_PIN_SET); } while(0)
#define NUM_F7 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_B_Pin|SEG_7_C_Pin|SEG_7_D_Pin, GPIO_PIN_SET); } while(0)
#define NUM_F8 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_B_Pin|SEG_7_C_Pin|SEG_7_D_Pin|SEG_7_E_Pin|SEG_7_F_Pin|SEG_7_G_Pin, GPIO_PIN_SET); } while(0)
#define NUM_F9 do{ HAL_GPIO_WritePin(GPIOB, SEG_7_A_Pin|SEG_7_B_Pin|SEG_7_C_Pin|SEG_7_D_Pin|SEG_7_E_Pin|SEG_7_G_Pin, GPIO_PIN_SET); } while(0)
/*------------------------------------------------------------------------------------------------------------------------------*/
/* 小时十位 */
#define HOUR_SHIWEI do{ HAL_GPIO_WritePin(GPIOC, Hour_Shiwei_Pin, GPIO_PIN_SET); } while(0)
/* 小时个位 */
#define HOUR_GEWEI do{ HAL_GPIO_WritePin(GPIOC, Hour_Gewei_Pin, GPIO_PIN_SET); } while(0)
/* 分钟十位 */
#define MIN_SHIWEI do{ HAL_GPIO_WritePin(GPIOC, Min_Shiwei_Pin, GPIO_PIN_SET); } while(0)
/* 分钟个位 */
#define MIN_GEWEI do{ HAL_GPIO_WritePin(GPIOC, Min_Gewei_Pin, GPIO_PIN_SET); } while(0)
/* 冒号 */
#define COLON_ON do{ HAL_GPIO_WritePin(GPIOC, _colon__Pin, GPIO_PIN_SET); } while(0)
#define COLON_OFF do{ HAL_GPIO_WritePin(GPIOC, _colon__Pin, GPIO_PIN_RESET); } while(0)
/*--------------------------------------------------------------------------------------------------------------------------------*/
/* 小时十位 */
#define H_SHIWEI 3
/* 小时个位 */
#define H_GEWEI 2
/* 分钟十位 */
#define M_SHIWEI 1
/* 分钟个位 */
#define M_GEWEI 0
#define LIGHTMAX 20000 //最大显示时间
显示函数:
亮度控制
void DelayLight(uint32_t sTime)
{
uint32_t tmp;
//亮灯时间
tmp = LIGHTMAX;
while (tmp > sTime)
{
tmp--;
}
NUM_X;
//灭灯时间
while (tmp > 0)
{
tmp--;
}
}正常显示
void LED_ShowNum(uint8_t Position, uint8_t _BCD)
{
uint32_t LightDelay = 0;
uint32_t tmp;
tmp = LIGHTMAX / 7;
/* 关闭显示 */
// NUM_X;
if (_BCD > 9 | Position > 3) return; //超出显示范围,退出
switch (_BCD)
{
case 0:
NUM_0;
LightDelay = LIGHTMAX - tmp * 6; //6 segment
break;
case 1:
NUM_1;
LightDelay = LIGHTMAX - tmp * 2; //2 segment
break;
case 2:
NUM_2;
LightDelay = LIGHTMAX - tmp * 5; //5 segment
break;
case 3:
NUM_3;
LightDelay = LIGHTMAX - tmp * 5; //5 segment
break;
case 4:
NUM_4;
LightDelay = LIGHTMAX - tmp * 4; //4 segment
break;
case 5:
NUM_5;
LightDelay = LIGHTMAX - tmp * 5; //5 segment
break;
case 6:
NUM_6;
LightDelay = LIGHTMAX - tmp * 6; //6 segment
break;
case 7:
NUM_7;
LightDelay = LIGHTMAX - tmp * 3; //3 segment
break;
case 8:
NUM_8;
LightDelay = LIGHTMAX - tmp * 7; //7 segment
break;
case 9:
NUM_9;
LightDelay = LIGHTMAX - tmp * 6; //6 segment
break;
// default:
// NUM_X;
}
switch (Position)
{
case 0:
MIN_GEWEI;
break;
case 1:
MIN_SHIWEI;
break;
case 2:
HOUR_GEWEI;
break;
case 3:
HOUR_SHIWEI;
break;
// default:
// NUM_X;
}
DelayLight(LightDelay);
}镜像显示
void LED_ShowNumMirror(uint8_t Position, uint8_t _BCD)
{
uint16_t LightDelay = 0;
uint32_t tmp;
tmp = LIGHTMAX / 7;
/* 关闭显示 */
// NUM_X;
if (_BCD > 9 | Position > 3) return; //超出显示范围,退出
switch (_BCD)
{
case 0:
NUM_F0;
LightDelay = LIGHTMAX - tmp * 6;
break;
case 1:
NUM_F1;
LightDelay = LIGHTMAX - tmp * 2;
break;
case 2:
NUM_F2;
LightDelay = LIGHTMAX - tmp * 5;
break;
case 3:
NUM_F3;
LightDelay = LIGHTMAX - tmp * 5;
break;
case 4:
NUM_F4;
LightDelay = LIGHTMAX - tmp * 4;
break;
case 5:
NUM_F5;
LightDelay = LIGHTMAX - tmp * 5;
break;
case 6:
NUM_F6;
LightDelay = LIGHTMAX - tmp * 6;
break;
case 7:
NUM_F7;
LightDelay = LIGHTMAX - tmp * 3;
break;
case 8:
NUM_F8;
LightDelay = LIGHTMAX - tmp * 7;
break;
case 9:
NUM_F9;
LightDelay = LIGHTMAX - tmp * 6;
break;
// default:
// NUM_X;
}
switch (Position)
{
case 0:
MIN_GEWEI;
break;
case 1:
MIN_SHIWEI;
break;
case 2:
HOUR_GEWEI;
break;
case 3:
HOUR_SHIWEI;
break;
// default:
// NUM_X;
}
DelayLight(LightDelay);
}
/* 日期 时间 镜像 显示日期 */
void ShowTime(RTC_DateTypeDef* sDate, RTC_TimeTypeDef* sTime, uint8_t ScreenMirror, uint16_t ShowDate)
{
void (* LED_Show)( uint8_t Position, uint8_t _BCD );
LED_Show = &LED_ShowNum;
if (ScreenMirror == 1) LED_Show = &LED_ShowNumMirror;
if (ShowDate == 0)
{//显示时间
//Hour
if ((HoursTwinkle && LightON) || !HoursTwinkle){
LED_Show(H_SHIWEI, (sTime->Hours & 0xF0) >> 4);
LED_Show(H_GEWEI, sTime->Hours & 0x0F);
}
//Minutes
if ((MinutesTwinkle && LightON) || !MinutesTwinkle){
LED_Show(M_SHIWEI, (sTime->Minutes & 0xF0) >> 4);
LED_Show(M_GEWEI, sTime->Minutes & 0x0F);
}
}
else
{//显示日期
//Month
if ((MonthTwinkle && LightON) || !MonthTwinkle){
LED_Show(H_SHIWEI, (sDate->Month & 0xF0) >> 4);
LED_Show(H_GEWEI, sDate->Month & 0x0F);
}
//Date
if ((DateTwinkle && LightON) || !DateTwinkle){
LED_Show(M_SHIWEI, (sDate->Date & 0xF0) >> 4);
LED_Show(M_GEWEI, sDate->Date & 0x0F);
}
}
}
二、RTC初始化
static void MX_RTC_Init(void)
{
/* USER CODE BEGIN RTC_Init 0 */
/* USER CODE END RTC_Init 0 */
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
/* USER CODE BEGIN RTC_Init 1 */
/* USER CODE END RTC_Init 1 */
/**Initialize RTC Only
*/
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN Check_RTC_BKUP */
// if ((hrtc.Instance->CR & RTC_CR_BKP) == (uint32_t)RESET)
if ((hrtc.Instance->ISR & RTC_ISR_INITS) == (uint32_t)RESET)
{
/* USER CODE END Check_RTC_BKUP */
/**Initialize RTC and set the Time and Date
*/
sTime.Hours = 0x12;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_NOVEMBER;
sDate.Date = 0x12;
sDate.Year = 0x18;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
/**Enable Calibration
*/
if (HAL_RTCEx_SetCalibrationOutPut(&hrtc, RTC_CALIBOUTPUT_1HZ) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN RTC_Init 2 */
// /* Disable the write protection for RTC registers */
// __HAL_RTC_WRITEPROTECTION_DISABLE(&hrtc);
// hrtc.Instance->CR |= (uint32_t)RTC_CR_BKP;//设置RTC初始化标志
// /* Enable the write protection for RTC registers */
// __HAL_RTC_WRITEPROTECTION_ENABLE(&hrtc);
} /* End if (hrtc.Instance->ISR & RTC_ISR_INITS) */
/* USER CODE END RTC_Init 2 */
}这里添加了检测RTC初始化的代码,数据手册说可以通过ISR寄存器的INITS位来检测,经过实际测试,当年份是xx00年的时候,不管有没有初始化,INITS都是为零。不过1-99年也足够用了。也可以采用CR寄存器的BKP位做初始化标识,见注释掉的代码。
三、MPU6050的初始化与数据读取
//初始化MPU6050
void InitMPU6050(void)
{
HAL_Delay(100);
Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠状态
Single_WriteI2C(SMPLRT_DIV, 0x07);
Single_WriteI2C(CONFIG, 0x06);
Single_WriteI2C(GYRO_CONFIG, 0x18);
Single_WriteI2C(ACCEL_CONFIG, 0x00);
}
//合成数据
uint16_t GetData(uint16_t REG_Address)
{
uint8_t H,L;
H=Single_ReadI2C(REG_Address);
L=Single_ReadI2C(REG_Address+1);
return (H<<8)+L;
}
//读取数据
void MPU6050Read(short *mData, uint8_t reg_add)
{
mData[0] = (short) GetData(reg_add);
mData[1] = (short) GetData(reg_add);
mData[2] = (short) GetData(reg_add);
}
四、I2C读写
//**************************************
//向I2C设备写入一个字节数据
//**************************************
void Single_WriteI2C(uint16_t REG_Address,uint8_t REG_data)
{
HAL_StatusTypeDef hal_status;
hal_status = HAL_I2C_Mem_Write(&hi2c2, SlaveAddress, REG_Address, I2C_MEMADD_SIZE_8BIT, ®_data, sizeof(uint8_t), I2C_TIMEOUT);
if (hal_status != HAL_OK)
{
Error_Handler();
}
}
//**************************************
//从I2C设备读取一个字节数据
//**************************************
uint8_t Single_ReadI2C(uint16_t REG_Address)
{
uint8_t REG_data;
HAL_StatusTypeDef hal_status;
hal_status = HAL_I2C_Mem_Read(&hi2c2, SlaveAddress, REG_Address, I2C_MEMADD_SIZE_8BIT, ®_data, sizeof(uint8_t), I2C_TIMEOUT);
if (hal_status != HAL_OK)
{
Error_Handler();
}
return REG_data;
}
五、按键检测
宏定义及函数声明
#define KEYDOWNLTIME 3000 #define TREMBLINGTIME 10 #define DOWN 0x80 #define LONGDOWN 0x40 #define RELEASE 0x20 #define TREMBLING 0x10 #define VALID 0x01 #define NOKEYDOWN 0x00 uint8_t GetKeyState(void); void UserKeyTest(void); void ClearKeyState(void);
按键代码:
/**************************************
* 按键状态
* bits_7=1,键按下
* bits_6=1,长按
* bits_5=1,键释放
* bits_4=1,键消抖 =0,没有消抖
* bits_3=1,
* bits_2=1,
* bits_1=1,
* bits_0=1,按键有效
**************************************/
__IO uint8_t KeyState = 0;
uint32_t KeyDownTimes = 0;
uint32_t TremblingTimes = 0;
void UserKeyTest(void)
{
static GPIO_PinState SetKey = GPIO_PIN_SET;
GPIO_PinState SetKeytmp;
if ((KeyState & VALID) != 0) return;//按键没有处理等待处理
if ((KeyState & TREMBLING) == 0)
{//消抖
TremblingTimes++;
if (TremblingTimes > TREMBLINGTIME) KeyState |= TREMBLING;//完成消抖动
return;
}
TremblingTimes = 0;
SetKeytmp = HAL_GPIO_ReadPin(SetKey_GPIO_Port, SetKey_Pin);
if (SetKey != SetKeytmp)
{//开始消除按键抖动
KeyState &= ~TREMBLING;
SetKey = SetKeytmp;
return;
}
/* SetKey = 1,按键没有按下或已释放,SetKey = 0,按键按下 */
SetKey = SetKeytmp;
if ((KeyState & LONGDOWN) != 0)
{//如果是长按状态,则等待键释放
if (SetKey == RESET)
{
return;
}
else
{
KeyDownTimes = 0;
KeyState = NOKEYDOWN;
}
}
if (SetKey == RESET)
{//有键按下
if ((KeyState & DOWN) != 0)
{
KeyDownTimes++;
if (KeyDownTimes > KEYDOWNLTIME)
{
KeyState |= LONGDOWN;//长按
KeyState |= VALID;//长按
}
}
else
{
KeyState |= DOWN;
}
}
else
{//无键按下
KeyDownTimes = 0;
if ((KeyState & DOWN) != 0)
{
KeyState |= RELEASE;
KeyState |= VALID;
}
}/* END if (SetKey == RESET) */
}
/* 返回按键状态 */
uint8_t GetKeyState(void)
{
return KeyState;
}
/* 解除按键状态 */
void ClearKeyState(void)
{
KeyDownTimes = 0;
KeyState = KeyState & LONGDOWN;
}
按键利用系统定时器1ms中断函数void SysTick_Handler(void)来进行检测
六、冒号闪烁:
利用RTC产生的秒中断实现,在外部中断程序里添加如下代码:
void EXTI0_1_IRQHandler(void)
{
/* USER CODE BEGIN EXTI0_1_IRQn 0 */
//冒号闪烁
if (HAL_GPIO_ReadPin(LD2_GPIO_Port, LD2_Pin) != GPIO_PIN_RESET)
{
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
COLON_OFF;
LightON = 0;
}
else
{
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
if (SecON) COLON_ON;
LightON = 1;
}
/* USER CODE END EXTI0_1_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
/* USER CODE BEGIN EXTI0_1_IRQn 1 */
/* USER CODE END EXTI0_1_IRQn 1 */
}
七、主程序及变量定义
__IO uint8_t SecON = 1; //秒显示开关,默认显示
__IO uint8_t LightON = 0; //闪烁时灯的开关
__IO uint8_t YearTwinkle = 0; //年闪烁开关
__IO uint8_t MonthTwinkle = 0; //月闪烁开关
__IO uint8_t DateTwinkle = 0; //日闪烁开关
__IO uint8_t HoursTwinkle = 0; //时闪烁开关
__IO uint8_t MinutesTwinkle = 0; //分闪烁开关
__IO uint8_t ScreenMirror = 0;
int main(void)
{
/* USER CODE BEGIN 1 */
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
uint8_t KeyState = 0;
uint8_t screenmirror = 0;
uint16_t showdatetime = 0;
short acc_x[3], acc_y[3], acc_z[3], gy_x[3], gy_y[3], gy_z[3], temp;
char tmp[50];
float temptmp;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_RTC_Init();
MX_I2C2_Init();
MX_ADC_Init();
/* Initialize interrupts */
MX_NVIC_Init();
/* USER CODE BEGIN 2 */
InitMPU6050();
ClearKeyState();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* 读取日期和时间 */
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BCD);
HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BCD);
/* 读取MPU6050 */
MPU6050Read(acc_x, ACCEL_XOUT_H);
MPU6050Read(acc_y, ACCEL_YOUT_H);
MPU6050Read(acc_z, ACCEL_ZOUT_H);
MPU6050Read(gy_x, GYRO_XOUT_H);
MPU6050Read(gy_y, GYRO_YOUT_H);
MPU6050Read(gy_z, GYRO_ZOUT_H);
temp = (short) GetData(TEMP_OUT_H);
// sprintf(tmp, "Acc: %8d, %8d, %8d \r\n", acc_x[0], acc_x[1], acc_x[2]);
// temptmp = ((double) temp / 340.0) + 36.53;
if (acc_x[2] < 0) screenmirror = 0; else screenmirror = 1;
// sprintf(tmp, "TEMP: %8.2f \r\n", temptmp);
/* 按键处理 */
KeyState = GetKeyState();
if (((KeyState & VALID) != 0) && ((KeyState & DOWN) != 0))
{//短按一下显示月、日
showdatetime = 500;
/* 按键处理完毕解除按键状态 */
ClearKeyState();
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
ShowTime(&sDate, &sTime, screenmirror, showdatetime); //显示
if (showdatetime != 0) showdatetime--;
}
/* USER CODE END 3 */
}这里只利用了MPU6050的X轴的数据,没有进行具体的分析计算。说实话吧,我对MPU6050不太熟,呵呵。
GPIO、I2C、NVIC等的初始化基本是CubeMX自动生成的,默认就行
代码里大部分都有注释。
最后上两张照片
正常显示

镜像显示

至此这个项目就算完成了,后续需要什么功能就添加,在此也不多说了。
感谢你看完这个,错误遗漏之处在所难免,多包涵。谢谢!
我要赚赏金
