零、前言
省流:目前完成所有功能,项目已上传
鉴于本次培训时间较短,且此次作业有一定难度,作为我的第一个嵌入式项目,共用了8个小时的时间进行开发,目前完成所有功能。但是这8小时已经基本消耗了我的耐心,暂时不会讲解各模块原理,后续有空再说。
目前仍存在不足,仅供参考,欢迎交流。
一、功能要求
(1)设备上电后,显示学生的手机号。测量显示当前装置的 X、Y、Z 三个方向的角速度,其中当装置平放时,红色 LED 以 0.2s 周期闪烁,按键 1 可关闭。当装置竖直放置时,绿色 LED
以 0.3S 周期闪烁,按键 2 可关闭。(40 分)
- IIC 初始化函数(15):
- LED 闪烁函数与 LCD 显示数字函数(25):
(2)测量显示当前装置的 X、Y、Z 三个方向的加速度。当装置水平往右运动时,红色 LED 以
0.1s 周期闪烁,按键 3 可关闭。当装置垂直往上运动时,绿色 LED 以 0.15S 周期闪烁,按键 4 可
关闭;(25 分)
- 加速度测量与计算函数(25):
(3)定时通过串口上报加速度与角速度值,第一次上报时间为 12 时 0 点 0 分,此后每隔 10
秒上报一次,同时在 LCD 上显示时间;(15 分)
命令格式([时间]:[Ax=加速度 X 值]+[Ay=加速度 Y 值]+[Az=加速度 Z 值] [命令结束
标志])如下:
举例:“123030:Ax=65530+Ay=100+Az=80\n” //12 时 30 分 30 秒上报加速度值为
Ax=65530,Ay=100,Az=80。
(4)可通过串口修改上报时间间隔(范围 0-10)并掉电保存;(15 分)
命令格式([命令类型][数值][命令结束标志])如下:
举例:“T1\n”//设置上报间隔秒为 1;装置接收到命令执行后,回复“T1ok\n”。
(5)其他功能。(5 分)
二、各模块代码
0.引脚配置
1.主循环
while (1)
{
Judge_State();//判断运动状态
Read_Sensor();//读取三维传感器数据
Show_Inf();//LCD显示
UART_T_R();//串口收发
Flash_func();flash写入
HAL_Delay(20);
}
2.传感器读取
void Read_Sensor(void)
{
Lsm6ds3_ReadAccelerationRaw(buf1);
Lsm6ds3_ReadAngularRateRaw(buf2);
}
3.运动状态判断
3.1运动状态判断主函数
void Judge_State(void)
{
if(buf1[2]<-12000&&!Sigma_X()&&!Sigma_Z())//z
{
state=1;
}
else if(buf1[1]<-12000&&!Sigma_X())//y
{
state=2;
}
else if(Sigma_X())//x
{
state=3;
}
else if(Sigma_Z()&&sigma_z[4]!=0)//z
{
state=4;
}
else
state=0;
}
3.2X/Z轴"速度"(加速度求和)计算函数
int Sigma_X(void)
{
int sum=0;
for(int i=1;i<5;i++)
sum+=sigma_x[i];
for(int i=4;i>1;i--)
sigma_x[i]=sigma_x[i-1];
sigma_x[1]=buf1[0];
sigma_x[0]=sum;
return sigma_x[0]<-1000?1:0;
}
int Sigma_Z(void)
{
int sum=0;
for(int i=1;i<5;i++)
sum+=sigma_z[i];
for(int i=4;i>1;i--)
sigma_z[i]=sigma_z[i-1];
sigma_z[1]=buf1[2];
sigma_z[0]=sum;
return sigma_z[0]>-62500?1:0;
}
4. 串口发送数据
void Serial_Send_Inf(void)
{
RTC_DateTypeDef Nowdate;
RTC_TimeTypeDef Nowtime;
HAL_RTC_GetTime(&hrtc,&Nowtime, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc,&Nowdate, RTC_FORMAT_BIN);
printf("Now Time :%d-%d-%d-%d-%d-%d State:%d \r\n",Nowdate.Year+2000,Nowdate.Month,Nowdate.Date,Nowtime.Hours,Nowtime.Minutes,Nowtime.Seconds,state);
printf("Acceleration:%d %d %d\r\n",buf1[0],buf1[1],buf1[2]);
printf("AngularRate: %d %d %d\r\n",buf2[0],buf2[1],buf2[2]);
printf("read data = %02x \r\n",readnum);
}
5.LCD信息显示
void Show_Inf(void)
{
//Lcd_Clear(WHITE);
Gui_DrawFont_GBK24(100,0,BLACK,WHITE,(uint8_t*)"Matr1x");
char str[10];
for(int i=0;i<3;i++)
{
sprintf(str,"%5d",buf1[i]);
Gui_DrawFont_GBK24(80*i,50,BLACK,WHITE,str);
sprintf(str,"%5d",buf2[i]);
Gui_DrawFont_GBK24(80*i,100,BLACK,WHITE,str);
}
Gui_DrawFont_Num32(100,160,BLACK,WHITE,state);
char time[30];
RTC_DateTypeDef Nowdate;
RTC_TimeTypeDef Nowtime;
HAL_RTC_GetTime(&hrtc,&Nowtime, RTC_FORMAT_BIN);//???????
HAL_RTC_GetDate(&hrtc,&Nowdate, RTC_FORMAT_BIN);//?????,????????
sprintf(time,"%d.%d.%d %d:%d:%d",Nowdate.Year+2000,Nowdate.Month,Nowdate.Date,Nowtime.Hours,Nowtime.Minutes,Nowtime.Seconds);
Gui_DrawFont_GBK24(100,250,BLACK,WHITE,time);
}
6. 串口收发
void HAL_UART_RxCpltCallback (UART_HandleTypeDef *huart)
{
if(huart==&huart2)
{
rf=1;
}
}
//串口收发函数
void UART_T_R(void)
{
if(rf==1)
{
rf=0;
readnum=dat[1]*10+dat[0];
printf("read data = %02x \r\n",readnum);
HAL_UART_Receive_IT(&huart2,dat,1);
}
}
7.flash写入
void Flash_func(void)
{
uint32_t add_num;
add_num = *(uint32_t *)0x08040000;
// printf("read data = %02x \r\n",add_num);
if(add_num!=readnum)
{
add_num=readnum;
HAL_TIM_Base_Start_IT(&htim7);
MX_TIM7_Init();
HAL_FLASH_Unlock();
FLASH_EraseInitTypeDef erase_init;
uint32_t page_error = 0U;
erase_init.Page = 0;
erase_init.NbPages = 1;
erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
erase_init.Banks = FLASH_BANK_2;
HAL_FLASHEx_Erase(&erase_init, &page_error);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, 0x08040000, readnum);
HAL_FLASH_Lock();
}
}
8. 定时器回调——LED闪烁+串口发送
8.1定时器回调主函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim==(&htim6))
{
switch(state)
{
case 1:{
Period = 2000;
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10,GPIO_PIN_RESET);
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);
break;
}
case 2:{
Period = 3000;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0,GPIO_PIN_RESET);
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_10);
break;
}
case 3:{
Period = 1000;
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10,GPIO_PIN_RESET);
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);
break;
}
case 4:{
Period = 1500;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0,GPIO_PIN_RESET);
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_10);
break;
}
default:
break;
}
//HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);
//LED_Period(1);
}
if(htim==(&htim7))
{
Serial_Send_Inf();
}
}
8.2修改定时器为可变周期
9.外部中断——按键关闭LED
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
switch(GPIO_Pin)
{
case GPIO_PIN_1:case GPIO_PIN_3:{//state=1/3
HAL_TIM_Base_Stop_IT(&htim6);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0,GPIO_PIN_RESET);
break;
}
case GPIO_PIN_0:case GPIO_PIN_4:{//state=2/4
HAL_TIM_Base_Stop_IT(&htim6);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10,GPIO_PIN_RESET);
break;
}
break;
}
}
三、源码
源码仅供参考