实验目的
1.使用PSoc62?芯片读取内部rtc时间
2.OLED屏幕显示当前时间戳
实验准备
- PSoc62?开发板
- SSD1306 OLED模块
- 公母头杜邦线
芯片资源
PSoC 6系列MCU时钟系统由以下几部分组成,PSoc62?开发板没有接外部时钟源,所以只能从IMO、ILO、PILO里边配置
- 三个内部的时钟源
- 8-MHz internal main oscillator (IMO)
- 32-kHz internal low-speed oscillator (ILO)
- Precision 32-kHz internal low-speed oscillator (PILO)
- 三个外部的时钟源
- External clock (EXTCLK) generated using a signal from an I/O pin
- External 16–35 MHz crystal oscillator (ECO)
- External 32-kHz watch crystal oscillator (WCO)
组件配置
rtc配置,这里的RTC_USING_LSI指的是ILO
使能u8g2软件包,这里使用软件的方式模拟i2c时序
注意要在代码里边绑定i2c引脚,pin number和GPIO的对应关系:
#define OLED_I2C_PIN_SCL 64 // P8.0 #define OLED_I2C_PIN_SDA 65 // P8.1
模块电路
GPIO引脚
MCU_ARD_SCL -> P8.0
MCU_ARD_SDA -> P8.1
模块连接图
右侧排母从上往下第1、2引脚分别对应SCL、SDA
实物连接
依次连接OLED模块的VCC、GND、SDL、SDA引脚
程序设计
Infineon PSoc?62时钟源设置代码
#ifdef BSP_RTC_USING_LSE Cy_RTC_SelectClockSource(CY_RTC_CLK_SELECT_WCO); #else Cy_RTC_SelectClockSource(CY_RTC_CLK_SELECT_ILO); #endif
由于RT-Thread HAL_Drivers不太完善,这里需要修改RTC HAL层的代码,把上面的代码添加到
static int rt_hw_rtc_init(void) { rt_err_t result = RT_EOK; ifx32_rtc_dev.ops = &_rtc_ops; if (rt_hw_rtc_register(&ifx32_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL) != RT_EOK) { LOG_E("rtc init failed"); result = -RT_ERROR; } else { LOG_D("rtc init success"); } #ifdef BSP_RTC_USING_LSE Cy_RTC_SelectClockSource(CY_RTC_CLK_SELECT_WCO); #else Cy_RTC_SelectClockSource(CY_RTC_CLK_SELECT_ILO); #endif if (cyhal_rtc_init(&rtc_obj) != RT_EOK) { LOG_E("rtc init failed."); return -RT_ERROR; } return RT_EOK; return result; }
OLED驱动,读取当前系统时间戳并显示到屏幕
void oled_display() { time_t now; struct tm *p_tm; u8g2_t u8g2; char buffer[50]; // Initialization u8g2_Setup_ssd1306_i2c_128x64_noname_f( &u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_rtthread); u8x8_SetPin(u8g2_GetU8x8(&u8g2), U8X8_PIN_I2C_CLOCK, OLED_I2C_PIN_SCL); u8x8_SetPin(u8g2_GetU8x8(&u8g2), U8X8_PIN_I2C_DATA, OLED_I2C_PIN_SDA); u8g2_InitDisplay(&u8g2); u8g2_SetPowerSave(&u8g2, 0); // Draw Graphics /* full buffer example, setup procedure ends in _f */ u8g2_ClearBuffer(&u8g2); u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr); u8g2_DrawStr(&u8g2, 1, 18, "U8g2 on RT-Thread"); u8g2_SendBuffer(&u8g2); u8g2_SetFont(&u8g2, u8g2_font_unifont_t_symbols); u8g2_DrawGlyph(&u8g2, 112, 56, 0x2603 ); u8g2_SendBuffer(&u8g2); for (;;) { u8g2_ClearBuffer(&u8g2); u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr); now = time(RT_NULL); p_tm = localtime(&now); memset(buffer, 0, 50); snprintf(buffer, 50, "%d-%d-%d %d:%d:%d ", p_tm->tm_year+ 1900, p_tm->tm_mon + 1, p_tm->tm_mday, p_tm->tm_hour, p_tm->tm_min, p_tm->tm_sec); u8g2_DrawStr(&u8g2, 1, 18, buffer); u8g2_SendBuffer(&u8g2); rt_thread_mdelay(1000); } }
整合代码
#include <rtthread.h> #include <rtdevice.h> #include <time.h> #include "drv_gpio.h" #include "drivers/alarm.h" #include <rtdbg.h> #include <u8g2_port.h> #define OLED_I2C_PIN_SCL 64 // P8.0 #define OLED_I2C_PIN_SDA 65 // P8.1 #define RTC_NAME "rtc" static rt_device_t device = RT_NULL; static int uesr_rtc_init(void) { rt_err_t ret = RT_EOK; time_t now; device = rt_device_find(RTC_NAME); if (!device) { rt_kprintf("find %s failed!", RTC_NAME); return RT_ERROR; } if(rt_device_open(device, 0) != RT_EOK) { rt_kprintf("open %s failed!", RTC_NAME); return RT_ERROR; } ret = set_date(2024, 1, 20); if (ret != RT_EOK) { rt_kprintf("set RTC date failed "); return ret; } ret = set_time(16, 55, 50); if (ret != RT_EOK) { rt_kprintf("set RTC time failed "); return ret; } now = time(RT_NULL); rt_kprintf("RTC device init success,now time is %s ", ctime(&now)); return ret; } INIT_APP_EXPORT(uesr_rtc_init); void oled_display() { time_t now; struct tm *p_tm; u8g2_t u8g2; char buffer[50]; // Initialization u8g2_Setup_ssd1306_i2c_128x64_noname_f( &u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_rtthread); u8x8_SetPin(u8g2_GetU8x8(&u8g2), U8X8_PIN_I2C_CLOCK, OLED_I2C_PIN_SCL); u8x8_SetPin(u8g2_GetU8x8(&u8g2), U8X8_PIN_I2C_DATA, OLED_I2C_PIN_SDA); u8g2_InitDisplay(&u8g2); u8g2_SetPowerSave(&u8g2, 0); // Draw Graphics /* full buffer example, setup procedure ends in _f */ u8g2_ClearBuffer(&u8g2); u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr); u8g2_DrawStr(&u8g2, 1, 18, "U8g2 on RT-Thread"); u8g2_SendBuffer(&u8g2); u8g2_SetFont(&u8g2, u8g2_font_unifont_t_symbols); u8g2_DrawGlyph(&u8g2, 112, 56, 0x2603 ); u8g2_SendBuffer(&u8g2); for (;;) { u8g2_ClearBuffer(&u8g2); u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr); now = time(RT_NULL); p_tm = localtime(&now); memset(buffer, 0, 50); snprintf(buffer, 50, "%d-%d-%d %d:%d:%d ", p_tm->tm_year+ 1900, p_tm->tm_mon + 1, p_tm->tm_mday, p_tm->tm_hour, p_tm->tm_min, p_tm->tm_sec); u8g2_DrawStr(&u8g2, 1, 18, buffer); u8g2_SendBuffer(&u8g2); rt_thread_mdelay(1000); } } int main(void) { oled_display(); return 0; }
实验效果
在msh终端敲命令date,即可查看开发板rtc时间
同时OLED模块实时显示当前时间