❶ 点亮LED
1.1 软件资料下载:
链接:工具 - 瑞萨 RA MCU 生态社区(https://www.ramcu.cn/lists/21.html)
下载开发板资料,如图:
1.2 板卡的固件下载
资料列表:
板卡内容组成(我没有收到线),而且我们的板子和这里的不一样(可能还要自己买个J-link)。
直接可以使用USB线下载代码:
板子不一样,查看一下EK-RA2E1的原理图。
1.3 原理图
链接::https://www.renesas.cn/cn/zh/products/microcontrollers-microprocessors/ra-cortex-m-mcus/ek-ra2e1-evaluation-kit-ra2e1-mcu-group
→注册后下载资料。
1.4 使用串口下载固件
参考:《使用UART串口烧写程序到瑞萨芯片.pptx》;
连接MCU下载固件:
下载成功了,但是LED没有闪烁。MCU选择如下:
修改MCU型号:
测试了P103发现引脚的电平没有变化,根据原理图来看,GPIO控制的是高电平端,如图:
上电,LED直接熄灭了。
修改时钟源:LOCO,
LED依旧常量。
修改代码LED正常闪烁
代码错误,没有加入while(1)循环:
时钟:LOCO 32768Hz(可以闪烁);HOCO 48MHZ(可以闪烁);MCU型号:R7FA2E1A72DNE;
小结:加入在生成的hal_entry()函数加入while()控制后,LED正常闪烁!
异常:确认,选择MCU型号-R7FA2L1AB2DFLLED不能点亮。
总结:开发板非常小巧,开发环境也很紧凑,但是即便是点灯,对新手也不太友好。
❷ 硬件IIC驱动LCD和LM75温度传感器
1、驱动LCD
野火也有RA系列的教程,链接:如何安装e2 studio/Keil开发环境 — [野火]瑞萨RA系列FSP库开发实战指南——基于野火启明开发板 文档(https://doc.embedfire.com/mcu/renesas/fsp_ra/zh/latest/doc/chapter2/chapter2.html)
从教程中得知,不能使用DAP仿真器(那基本上ST-LINK就更不要想了):
不过,没有关系,上一节已经实现了串口下载固件,继续往下走。当前计划使用IIC驱动一款显示屏,驱动的显示屏选择:oled12864, 如图:
设置IIC功能:
安装资料包中的PPT,针对IIC外设的使用,基本操作都讲到了。按照教程,增加IIC外设→属性:
当前P400引脚上没有输出信号:
需要注意的是:生成的工程使用rtos的时候,默认是没有之前的 hal_entry()函数调用了;所以这里已经没有调用之前的LED的初始化代码了,如图:
将OLED的初始化放到相关任务后,发现LED就不亮了;注释掉OLED操作的香瓜代码后,LED正常闪烁。最有可能是IIC的操作有错误,导致程序卡死了。现在没有初始化串口,所以暂时使用LED的亮灭状态来调试代码。
接上oled能够在示波器上看到IIC相关波形,如图:
所以,推测IIC初始化肯定成功了,只需要排除接线问题。果然,排除接线问题后,oled12864显示正常,如图:
这里的OLED驱动代码暂时也是使用的资料包里面的例程,后面会上U8G2显示库。
2、驱动温度传感器
刚好有一个LM75温度传感器。简单看了一下时序:
简单看了设置寄存器,在这里并不想使用输出报警功能,只要能够读取实时温度就行。
正常的IIC通信时序:
IIC的通信知识点有点陌生了,找了几张图补充了一下知识点:
寄存器地址:
应该连起来看,首先是设置指针寄存器,然后就可以随便读取温度了。
尝试定义多个IIC对象
在这里OLED和LM75都是使用的硬件IIC,所以尝试定义多个IIC对象:
这里定义了2个IIC对象,结果发现固件下载后,直接异常了,OLED不显示,温度不能采集:
所以只能换一种方式,点击相关属性的感叹号,能够找到一主多从的解析:
抓取了部分代码:
/* Send data to I2C slave on the same channel */
err = R_IIC_MASTER_SlaveAddressSet(&g_i2c_device_ctrl_2, I2C_SLAVE_DISPLAY_ADAPTER, I2C_MASTER_ADDR_MODE_7BIT);
assert(FSP_SUCCESS == err);
g_i2c_tx_buffer[0] = 0xAA; // NOLINT
g_i2c_tx_buffer[1] = 0xBB; // NOLINT
g_i2c_callback_event = I2C_MASTER_EVENT_ABORTED;
timeout_ms = I2C_TRANSACTION_BUSY_DELAY;
err = R_IIC_MASTER_Write(&g_i2c_device_ctrl_2, &g_i2c_tx_buffer[0], 2U, false);
assert(FSP_SUCCESS == err);
while ((I2C_MASTER_EVENT_TX_COMPLETE != g_i2c_callback_event) && timeout_ms)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
timeout_ms--;;
}
if (I2C_MASTER_EVENT_ABORTED == g_i2c_callback_event)
{
__BKPT(0);
}
显示温度效果:
❸ 基于U8G2显示菜单
任务之间传递变量:
发现当硬件I2C的不同的外设放到不同的任务的时候,会引发未知错误,外设不能正常工作,暂时放弃。
移植U8g2-硬件IIC
移植完成:
参考链接:STM32 U8g2 spi软件驱动,spi硬件驱动_u8g2 驱动_weixin_58595117的博客-CSDN博客
主要修改函数:
uint8_t u8x8_byte_3wire_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t *p = (uint8_t*) arg_ptr;
static _Bool flagCmdData = 0;
switch (msg)
{
/*通过SPI发送arg_int个字节数据*/
case U8X8_MSG_BYTE_SEND:
for (int i = 0; i < arg_int; i++)
{
if (flagCmdData)
{
OLED_WR_DATA ((uint8_t) *(p + i));
}
else
{
OLED_WR_CMD ((uint8_t) *(p + i));
}
}
break;
/*设置DC引脚,DC引脚控制发送的是数据还是命令*/
case U8X8_MSG_BYTE_SET_DC:
if (arg_int)
{
flagCmdData = 1;
}
else
{
flagCmdData = 0;
}
break;
/*初始化函数*/
case U8X8_MSG_BYTE_INIT:
// SPI_OLED_Init ();
break;
/* 下面功能无需定义 */
/*开始传输前会进行的操作,如果使用软件片选可以在这里进行控制*/
case U8X8_MSG_BYTE_START_TRANSFER:
break;
/*传输后进行的操作,如果使用软件片选可以在这里进行控制*/
case U8X8_MSG_BYTE_END_TRANSFER:
break;
default:
return 0;
}
return 1;
}
画图
使用普通软件取模生成的数组,u8g2_DrawGlyph(&u8g2,
112, 56, _air_conditioner_4x_t ); 不能显示,需要使用函数 u8g2_DrawXBM(&u8g2,
13,23, 30, 23, _air_conditioner_4x_t)。
生成bmp文件
使用画图软件调整大小:
生成数组
使用取模软件 -PCtoLCD2022:
代码
const uint8_t _clock_4x_t[ ] ={
0x00,0xFC,0x07,0x00,0x00,0xFF,0x1F,0x00,0xC0,0xFF,0x7F,0x00,0xE0,0x03,0xF8,0x00,
0xF0,0xE0,0xE0,0x01,0x78,0xE0,0xC0,0x03,0x3C,0xE0,0x80,0x07,0x1C,0xE0,0x00,0x07,
0x0E,0xE0,0x00,0x0E,0x0E,0xE0,0x00,0x0E,0x07,0xE0,0x00,0x1C,0x07,0xE0,0x00,0x1C,
0x07,0xE0,0x00,0x1C,0x07,0xF0,0x01,0x1C,0x07,0xF0,0x01,0x18,0x07,0xF0,0x01,0x1C,
0x07,0xE0,0x03,0x1C,0x07,0x80,0x07,0x1C,0x07,0x00,0x0F,0x1C,0x0E,0x00,0x1E,0x0E,
0x0E,0x00,0x1C,0x0E,0x1C,0x00,0x00,0x0F,0x3C,0x00,0x00,0x07,0x78,0x00,0x80,0x03,
0xF0,0x00,0xE0,0x01,0xE0,0x03,0xF8,0x00,0xC0,0xBF,0x7F,0x00,0x00,0xFF,0x3F,0x00,
0x00,0xFC,0x07,0x00,0x00,0x00,0x00,0x00,/*"D:\BaiduNetdiskDownload\图标\时钟.bmp",0*/
/* (30 X 30 )*/
};
显示图片:u8g2_DrawXBM(&u8g2, 13,23, 30, 30, _clock_4x_t);
需要注意的问题:u8g2_NextPage
u8g2_NextPage()的返回值一直为1,所以菜单页面不会更新。
修改 to_right( )函数:
当前显示温度需要关闭显示才能采集,因为温度采集和OLED显示都是使用硬件IIC,会产生冲突,所以这里针对U8G2做了一点改动,采集温度的时候关闭显示。底层代码逻辑:
关键变量:u8x8_d_ssd1306_128x64_noname_powersave0_seq、u8x8_d_ssd1306_128x64_noname_powersave1_seq。
详细显示如下:
static const uint8_t u8x8_d_ssd1306_128x64_noname_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_128x64_noname_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
实际上调用display off会导致屏幕熄灭,体验不好,所以,将display off 的寄存器进行修改:0x0ae → 0x0af 。骗过U8G2驱动,关闭U8G2不会真的关闭OLED的显示。
按键驱动
按键驱动做的比较粗糙,只有几个状态:短按、短按释放、长按、长按释放。菜单的显示框架参考RTT。
参考:
RTT-thread进行按键驱动的移植:https://packages.rt-thread.org/index.html。
关于按键消抖的时间描述:https://packages.rt-thread.org/detail.html?package=agile_button ;
基于RTT的例子:https://gitee.com/RT-Thread-Mirror/rt-u8g2/
如图:
❹红外解码
1、为红外解码启动定时器
当前选择的模块,是费了很大心思的,选择了一个十分好的模块,如图:
因为发射和接收模块,价格很好-9个十分(0.9元/个)。选好了模块,接下来就是使用定时器来驱动发射模块了。
当前配置了GPT定时器后,无法编译通过。单片机Flash不够报错,已经很久没有体验到单片机Flash不够而报错的感觉了。
错误:
d:/renesas_e2_studio/setup_fsp_v3_2_0_e2s_v2021-07/toolchains/gcc_arm/9_2020q2/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld.exe: oled12864.elf section .text' will not fit in region FLASH'
d:/renesas_e2_studio/setup_fsp_v3_2_0_e2s_v2021-07/toolchains/gcc_arm/9_2020q2/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld.exe: region `FLASH' overflowed by 3364 bytes
修改代码,减少数组定义,解决掉编译错误。
1.1、查阅RTOS的手册中关于定时器的资料
根据这里的意思,可以定位到GPT定时器中断。
RTSO的手中,有章节介绍怎样配置GPT定时器,那就说明RTOS和GPT定时器外设不冲突。
1.2、使用RTOS手册中的代码成功启用定时器
定时器配置:
代码启用定时器(没有采用PPT资料中的方式开启定时器):
//------------time0 -参数手册《e2_快速上手指南.pdf》
g_timer.p_api->open(g_timer.p_ctrl, g_timer.p_cfg);
g_timer.p_api->start(g_timer.p_ctrl);
//定时器回调函数
void gpt_callback(timer_callback_args_t *p_args) {
(void)p_args;
if(counterGptTime ==1){
R_IOPORT_PinWrite (&g_ioport_ctrl, BSP_IO_PORT_01_PIN_04, BSP_IO_LEVEL_HIGH);///<点亮
}else if(counterGptTime ==2){
counterGptTime =0;
R_IOPORT_PinWrite (&g_ioport_ctrl, BSP_IO_PORT_01_PIN_04, BSP_IO_LEVEL_LOW);///<熄灭
}
counterGptTime++;
}
2、解码数据2.1、解码数据-1ms
修改GPT定时器的中断,通过在定时器中判断引脚电平的方式来解码红外数据。当前获取到的数据,异常。
空调26℃→
重复解码,修改打印的次数:
解码数据异常,查看示波器的采样波形:
当前ms级的中断无法有效解码,优化方向:红外信号的检测任务需要微妙级别的定时器中断。
2.2、解码数据-10us
修改GPT定时器的中断的时间,中断间隔时间10us,抓取的数据如下:
现在对比开头的几行数据(前面4行),解码已经很准确,解码的时间误差在x*10us之内。
2.3、精确分析
1650us的高电平解码:在误差范围内。
650us的高电平解码:在误差范围内。
抓取比较长的数据,第37个长时间高电平脉冲:在误差范围内。
比较典型的9ms低电平解码:在误差范围内。
接下来可以根据红外信号解码的数据,还原红外信号的发送。
解码主要代码(当前的解码和发射都是使用同一个定时器,所以将定时器的周期修改为:26us -38KHZ):
void infraredKeyValueDetect(void)
{
R_IOPORT_PinRead (&g_ioport_ctrl, BSP_IO_PORT_01_PIN_02, &infrared_data.p_port_value_port_102);
infrared_data.counter++;
if (infrared_data.p_port_value_port_102_last != infrared_data.p_port_value_port_102)
{ ///<电平如果发生翻转,记录高电平时间
if (infrared_data.p_port_value_port_102 & BSP_IO_LEVEL_HIGH)
{ ///<上升沿时间
if((infrared_data.data_index_low <148)&&(infrared_data.counter>1)){///<防止数组越界,26us的电平是异常电平
infrared_data.data_record_low[infrared_data.data_index_low++] = infrared_data.counter;
}
infrared_data.counter =0;
}
else
{ ///<下降沿时间
if((infrared_data.data_index_hight <148)&&(infrared_data.counter>1)){
infrared_data.data_record_hight[infrared_data.data_index_hight++] = infrared_data.counter;
}
infrared_data.counter =0;
}
}
infrared_data.p_port_value_port_102_last = infrared_data.p_port_value_port_102; ///<保留上一次的GPIO电平值
///<任务每一次循环:间隔时间26us ->函数放在定时器回调函数!
if(infrared_data.counter > 1923){///<50ms秒钟空闲
infrared_data.counter =0;
}
}
3、MCU还原遥控器信号
红外发送有问题的原因,在红外发送二极管上不能检测到波形,原因:runStatus变量为bool型,没有进入下面的逻辑。
现在改为static int8_t runStatus = 0;,示波器能够检测到波形,如图:
但是程序运行会卡死,在RTOS中加大了相关任务的堆栈。
在红外发射引脚上,示波器能够抓取到,波形的起始位置有一个大概9ms的低电平,如图:
分析:波形反过来。
修改后,抓取要发送的信号进行比对:解码的信号和还原的信号,在波形时间上没有明显差异。
但是还原出来的信号和遥控器的信号还是有差异。
还原的信号和原始信号对比:还原出来的信号和遥控器的信号,在空闲的时候,还是有差异。
还原信号:
初始信号:
修改解码逻辑-将空闲状态取消,还原信号如下:
小结:当前只能确保红外发射管上的波形,接收管上的波形后面再确认。
END
点击阅读原文,免费申请