RA4M2开发IOT(9)----动态显示MEMS数据
RA4M2开发IOT.9--动态显示MEMS数据
- 概述
- 视频教学
- 样品申请
- 硬件准备
- 参考程序
- 定义变量
- 轻触切屏
- 静态标签
- 涂鸦界面
- LSM6DSV16X界面
- 主程序
概述
本工程在瑞萨 RA4M2 单片机上,利用 0.96ʺ 128×64 OLED 实时展示多源信息,并把 涂鸦状态和LSM6DSV16X 六轴 IMU 的运动数据(单/双击、温度、三轴加速度)以“无闪烁”方式动态刷到屏幕。
最近在瑞萨RA的课程,需要样片的可以加qun申请:925643491。
视频教学
https://www.bilibili.com/video/BV1aENbzhEYN
RA4M2开发IOT(9)----动态显示MEMS数据
样品申请
https://www.wjx.top/vm/rCrkUrz.aspx
硬件准备
首先需要准备一个开发板,这里我准备的是自己绘制的开发板,需要的可以进行申请。
主控为R7FA4M2AD3CFL#AA0
同时添加RA4M2_IOT扩展版。
参考程序
https://github.com/CoreMaker-lab/RA4M2_IOT
https://gitee.com/CoreMaker/RA4M2_IOT
定义变量
● g_oled_clear:只在切换页面或进入特定模式时置 1,触发一次 OLED_Clear(),
之后页面内容靠覆写更新,避免闪屏。
● g_tuya_num:你用它做 100-次计数(在 1 ms 定时循环里 +1),到 100 (~100 ms) 再刷新页面一次,减少 I²C 带宽。
/* ================== OLED Page Control ================== */
static uint8_t g_oled_clear = 1; // 1=需要清屏;0=正常增量刷新
static uint8_t g_oled_page = 0; // 当前页索引:0-Tuya 1-MEMS 2-Baro
static uint8_t g_tuya_num = 0; // 100ms 级计数器,用来节流页面刷新
AC
/* —— Tuya(涂鸦)配网状态 —— */
static uint8_t g_tuya_ap_mode = 0; // 1=处于 AP 快配;0=普通
static uint32_t g_tuya_ap_mode_num = 0; // AP 模式剩余倒计时 (ms)
轻触切屏
在button_wifi_ap长按配网添加轻触切屏
/******************************************************************************************************************** @brief 长按按键 3 s 进入配网模式 (发送 0x05 命令)*******************************************************************************************************************/
static void button_wifi_ap(void)
{// wifi_ap_numbsp_io_level_t p_port_value_pin_111;R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_11, &p_port_value_pin_111);if(p_port_value_pin_111)/* 松开 */wifi_ap_num=0;else//长按3s复位wifi{if(wifi_ap_num<3000)wifi_ap_num++;else if(wifi_ap_num==3000){g_oled_clear=1;// 切屏前清屏g_oled_page=0;// 0-Tuya 1-MEMS 2-Barog_tuya_ap_mode_num=60*1*1000;//1分钟AP配网wifi_ap_num++;printf("[BTN] wifi_ap_mode\r\n");fsp_err_t err = R_SCI_UART_Write(&g_uart0_ctrl, g_tuya_wifi_cfg, 8);if(FSP_SUCCESS != err) __BKPT();while(uart_wifi_TX_flag == false){}uart_wifi_TX_flag = false;}if(wifi_ap_num==100)//轻触切换OLED显示{g_oled_clear=1;// 下一帧先清屏if(g_oled_page<2)// 0-Tuya 1-MEMS 2-Barog_oled_page++;elseg_oled_page=0;}}
}
静态标签
在检测到 g_oled_page 变化时——由 button_wifi_ap() 轻触切换或上电初始化——一次性绘制对应页面的静态标签(页标题、固定字段名)。
只要 g_oled_clear == 1 就清屏并绘骨架;随后动态数值由各 OLED_DrawPage_* 覆写,不闪烁。
static void OLED_switch(void)
{if (g_oled_clear) // ← 仅当需切屏时进入{g_oled_clear = 0; // 标记已完成清屏OLED_Clear(); // ① 清显存并刷新,黑场一次switch (g_oled_page) // ② 根据当前页写“标签”{/* ---------- Page-0 : Tuya 模组 ---------- */case 0:OLED_ShowString(0, 0, (u8 *)"TUYA", 16,1);OLED_ShowString(0, 16, (u8 *)"WIFI MODE:", 16,1);OLED_ShowString(0, 32, (u8 *)"AP MODE:", 16,1);break;/* ---------- Page-1 : LSM6DSV16X ---------- */case 1:OLED_ShowString(0, 0, (u8 *)"MEMS_LSM6DSV16X", 12,1);OLED_ShowString(0, 12, (u8 *)"TAP:", 12,1);OLED_ShowString(60,12, (u8 *)"TEMP:", 12,1);OLED_ShowString(0, 24, (u8 *)"X(mg):", 12,1);OLED_ShowString(0, 36, (u8 *)"Y(mg):", 12,1);OLED_ShowString(0, 48, (u8 *)"Z(mg):", 12,1);break;/* ---------- Page-2 : LPS22DF 气压计 ------- */case 2:OLED_ShowString(0, 0, (u8 *)"MEMS_LPS22DF", 12,1);break;}OLED_Refresh(); // ③ 推送骨架到屏幕}
}
涂鸦界面
在 Page-0 下周期性(每 100×1 ms ≈ 100 ms)刷新两行动态信息:
● AP MODE 行:显示 AP 或 normal
● WIFI MODE 行:显示 g_tuya_mode_flag(0~4)。
同时根据 g_tuya_mode_flag 控制 60 s AP 配网倒计时,使文字在倒计时结束后回到 normal。
/* ------------ Page-0 : TUYA 模组信息 -------------------------------- */static void OLED_DrawPage_TUYA(void)
{/* ① 管理倒计时 ── 在线时清零;否则每 1 ms 递减 */if (g_tuya_mode_flag == 4) // 4 = 已连云g_tuya_ap_mode_num = 0;else if (g_tuya_ap_mode_num > 0)g_tuya_ap_mode_num--;/* ② 100 ms 节流:g_tuya_num 递增至 100 再刷新一次 */if (++g_tuya_num >= 100){g_tuya_num = 0;/* --- 行1: AP/normal --- */if (g_tuya_ap_mode_num > 0) // 倒计时仍在 → APOLED_ShowString(80,16,(u8 *)"AP ",16,1);else // 否则 normalOLED_ShowString(80,16,(u8 *)"normal",16,1);/* --- 行2: Wi-Fi work-mode 数字标志 --- */OLED_ShowNum(80, 32, g_tuya_mode_flag, 1, 16,1);OLED_Refresh(); // 推送局部变更}
}
LSM6DSV16X界面
在 Page-1 下每 100 ms 刷新:
- 单/双击状态文本 (up_down)
- 片内温度 (temperature_degC)
- X/Y/Z 三轴加速度(mg,带符号,小数点后两位)
/* ------------ Page-1 : MEMS_LSM6DSV16X -------------------------- */
static void OLED_DrawPage_MEMS(void)
{if(g_tuya_num<100)g_tuya_num++;else{g_tuya_num=0;/* ---------- 1. TAP 状态 ---------- */if(up_down==0)OLED_ShowString(24, 12, "Normal", 12, 1);//在坐标 (24,12)else if(up_down==1)OLED_ShowString(24, 12, "Single", 12, 1);//在坐标 (24,12)else if(up_down==2)OLED_ShowString(24, 12, "Double", 12, 1);//在坐标 (24,12)/* ---------- 2. 读取并显示片内温度 ---------- */int16_t data_raw_temperature;double_t temperature_degC;/* Read temperature data */memset(&data_raw_temperature, 0x00, sizeof(int16_t));// 清空原始数据缓存// 读取 LSM6DSV16X 的原始温度数据lsm6dsv16x_temperature_raw_get(&dev_ctx, &data_raw_temperature);// 将原始 LSB 数据转换为摄氏温度temperature_degC = lsm6dsv16x_from_lsb_to_celsius(data_raw_temperature);OLED_ShowNum (90, 12,(uint32_t)temperature_degC, 3, 12, 1);// 整数位OLED_ShowChar (110, 12, '.',12, 1);uint32_t t100 = (uint32_t)(temperature_degC * 100);OLED_ShowNum (116, 12,(uint32_t)t100%100, 2, 12, 1);// 整数位/* ---------- 3. 读取并显示 X/Y/Z 加速度 ---------- */int16_t data_raw_acceleration[3];double_t acceleration_mg[3];lsm6dsv16x_acceleration_raw_get(&dev_ctx, data_raw_acceleration);acceleration_mg[0] =lsm6dsv16x_from_fs8_to_mg(data_raw_acceleration[0]);acceleration_mg[1] =lsm6dsv16x_from_fs8_to_mg(data_raw_acceleration[1]);acceleration_mg[2] =lsm6dsv16x_from_fs8_to_mg(data_raw_acceleration[2]);if(acceleration_mg[0]<0)OLED_ShowChar (36, 24, '-',12, 1);elseOLED_ShowChar (36, 24, '+',12, 1);OLED_ShowNum (42, 24,(uint32_t)fabs(acceleration_mg[0]),5,12, 1);OLED_ShowChar (72, 24, '.',12, 1);t100=(uint32_t)(fabs(acceleration_mg[0])*100);OLED_ShowNum (78, 24,(uint32_t)t100%100,2,12, 1);if(acceleration_mg[1]<0)OLED_ShowChar (36, 36, '-',12, 1);elseOLED_ShowChar (36, 36, '+',12, 1);OLED_ShowNum (42, 36,(uint32_t)fabs(acceleration_mg[1]),5,12, 1);OLED_ShowChar (72, 36, '.',12, 1);t100=(uint32_t)(fabs(acceleration_mg[1])*100);OLED_ShowNum (78, 36,(uint32_t)t100%100,2,12, 1);if(acceleration_mg[2]<0)OLED_ShowChar (36, 48, '-',12, 1);elseOLED_ShowChar (36, 48, '+',12, 1);OLED_ShowNum (42, 48,(uint32_t)fabs(acceleration_mg[2]),5,12, 1);OLED_ShowChar (72, 48, '.',12, 1);t100=(uint32_t)(fabs(acceleration_mg[2])*100);OLED_ShowNum (78, 48,(uint32_t)t100%100,2,12, 1);OLED_Refresh();
// printf("Acceleration [mg]:%4.2f\t%4.2f\t%4.2f\r\n",
// acceleration_mg[0], acceleration_mg[1], acceleration_mg[2]);}
}
主程序
hal_entry() 的主循环中,负责把 MCU 采集到的实时传感器/通信状态 动态绘制到 0.96ʺ OLED——并确保在不同功能页之间平滑切换、无闪烁。
//切屏完成后不再清屏,保持增量刷新,避免闪烁OLED_switch();if(g_oled_page==0) /* Page-0 : Tuya 状态页 */OLED_DrawPage_TUYA();// 显示 Wi-Fi / AP 配网信息else if(g_oled_page==1)/* Page-1 : LSM6DSV16X 状态页 */OLED_DrawPage_MEMS();// 显示单/双击、温度、XYZ 加速度