一、前言
项目介绍:本项目旨在使用STM32WB55CEU6和OLED显示屏实现显示实时时间的功能,集成于单一设备中,用户可以方便的获取当前时间,以方便物联网设备的实时检测和调整。
在FastBond3的基础部分,绘制了详细的框图,这个过程包括了对整个系统的设计思路的梳理,以及各个模块之间的连接关系的确定。同时,也进行了物料的选型,确保选用的物料能够满足项目的性能需求和成本控制。接下来在kicad软件中完成了PCB的绘制工作和打板工作。在FastBond3挑战部分中,会继续完善设计,做出实物模型,并进行效果演示。
二、原理图及PCB介绍
晶振电路:
STM32WB55CEU6在使用时使用了两个晶振,分别是32.768KHz的低速晶振,用于RTC时钟的输入,RTC可以为系统实时记录当前系统时间和日期,不管芯片有没有掉电。如果想要使用RTC实时记录系统时间,则芯片需要额外接入额外的备用电源。32MHz的高速晶振作为系统时钟的来源。以及两个10pF的负载电容。
STM32WB系列微控制器集成了用于低功耗蓝牙和802.15.4无线电解决方案的高质量射频收发器。与传统电路相比,射频板的布局需要特别注意。在高频情况下,铜互连(走线)作为功能电路元件,会引入干扰,降低射频性能。由走线和焊盘产生的寄生元件对整个电路的性能有很大影响。必须仔细遵循布局规则,以减轻这些影响并实现所要求的性能。RF引脚需要一个特定的阻抗,所以我们需要匹配这些阻抗,否则会无法获得最大功率传输或信号强度较小,甚至根本不起作用,在这里添加了一个低通滤波器,为了减少干扰。
STM32WB55CEU6多协议无线和超低功耗器件内嵌功能强大的超低功耗无线电模块(符合蓝牙® 低功耗SIG规范5.0和IEEE 802.15.4-2011标准)。该器件内含专用的Arm® Cortex® -M0+,用于执行所有的底层实时操作。这些器件基于高性能Arm® Cortex®-M4 32位RISC内核(工作频率可达64 MHz),旨在实现超低功耗。该内核带有单精度浮点运算单元(FPU),支持所有ARM®单精度数据处理指令和数据类型。它还具备DSP指令集和增强应用安全的内存保护单元(MPU)。IPCC提供有六个双向通道的增强型处理器间通信。HSEM提供硬件信号量,用于在两个处理器之间共享公共资源。
- 无线电
- 2.4 GHz
- 射频收发器,支持Bluetooth® 5.3规范、IEEE 802.15.4-2011 PHY和MAC,支持Thread和Zigbee® 3.0
- 接收灵敏度:-96 dBm(蓝牙®低功耗,速率1 Mbps)、-100 dBm(802.15.4)
- 可编程输出功率,可达+6 dBm,步长为1 dB
- 集成式巴伦,用于降低BOM
- 支持2 Mbps
- 支持广播扩展
- 专用的Arm® 32位 Cortex® M0+ CPU 用于实时无线层
- 精确的RSSI,有助于控制功耗
- 适用于需要符合以下射频规定的系统:ETSI EN 300 328、EN 300 440、FCC CFR47第15部分,以及ARIB STD-T66
- 支持外部PA
- 用于优化匹配解决方案的集成无源器件(IPD)配套芯片(MLPF-WB-01E3或MLPF-WB55-02E3或MLPF-WB-02D3)
- 超低功耗平台
- 1.71 V至3.6 V电源
- – 40 °C至85 / 105 °C温度范围
- 关断模式下13 nA
- 600 nA待机模式 + RTC + 32 KB RAM
- 2.1 µA停机模式 + RTC + 256 KB RAM
- MCU活动模式:当RF和SMPS处于开启状态时,<53 µA / MHz
- 无线电:Rx 4.5 mA / Tx为0 dBm 5.2 mA
- 内核:带有FPU的Arm® 32位Cortex®-M4 CPU、在Flash存储器中实现零等待状态运行性能的自适应实时加速器(ART™加速器)、主频高达64 MHz,MPU,能够实现高达80 DMIPS的性能,具有DSP指令集
- 性能基准
- 1.25 DMIPS/MHz(Drystone 2.1)
- 219.48 CoreMark®(3.43 CoreMark/MHz@64 MHz)
- 能耗基准
- ULPMark™ CP得分303
- 供电和复位管理
- 高效率的嵌入式SMPS降压转换器,采用智能旁路模式
- 超级安全的低功耗BOR(下欠压复位),有5个可选阈值
- 超低功耗POR/PDR
- 可编程电压检测器(PVD)
- VBAT模式为 RTC 和备份寄存器供电
- 时钟源
- 32 MHz晶振配集成式微调电容器(无线电和CPU时钟)
- 32 kHz晶振,用于RTC(LSE)
- 内部低功耗32 kHz(±5%)RC(LSI1)
- 内部低功耗32 kHz(稳定性 ±500 ppm)RC(LSI2)
- 内部多速(100 kHz-48 MHz)振荡器,由LSE自动调整(精度高于±0.25%)
- 内置经工厂调校的16 MHz高速RC(±1%)
- 2个PLL用于系统时钟、USB、SAI和ADC
在设计中还使用到了指定厂家Seeed的排针,此排针是Seeed用于搭配XIAO系列的开发板使用的。
三、成品功能测试
打样的电路板进行焊接后如图,在这里会出现麻烦事,STM32WB55CEU6的封装是UFQFPN-48这种引脚在芯片底下的,所以焊接会十分麻烦,因为我身边没有加热台和锡膏这种设备,所以是我朋友帮助我焊接的。
关键代码及说明:
int main(void)
{
/* USER CODE BEGIN 1 */
/* 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();
/* Configure the peripherals common clocks */
PeriphCommonClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_RTC_Init();
/* USER CODE BEGIN 2 */
Bsp_I2c_Init();
Bsp_Oled_Init();
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, GPIO_PIN_SET);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &GetData, RTC_FORMAT_BIN);
OLED_ShowNum(0, 0, (2000+GetData.Year), 4, 16, 0);
OLED_ShowString(32, 0, ".", 16, 0);
OLED_ShowNum(36, 0, GetData.Month, 2, 16, 0);
OLED_ShowString(52, 0, ".", 16, 0);
OLED_ShowNum(56, 0, GetData.Date, 2, 16, 0);
OLED_ShowNum(0, 4, GetTime.Hours, 2, 16, 0);
OLED_ShowString(16, 4, ".", 16, 0);
OLED_ShowNum(20, 4, GetTime.Minutes, 2, 16, 0);
OLED_ShowString(36, 4, ".", 16, 0);
OLED_ShowNum(40, 4, GetTime.Seconds, 2, 16, 0);
}
/* USER CODE END 3 */
}
代码一开始主要是初始化RTC、I2C以及OLED外设,主函数里不断循环获取当前的时间,再通过oled的显示函数将当前获取到的时间显示到OLED上。
void OLED_WR_DATA(uint8_t data)
{
HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x40, I2C_MEMADD_SIZE_8BIT, &data, 1, 0x100);
}
void OLED_WR_CMD(uint8_t cmd)
{
HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x00, I2C_MEMADD_SIZE_8BIT, &cmd, 1, 0x100);
}
void OLED_Set_Pos(uint8_t x, uint8_t y)
{
OLED_WR_CMD(0xb0 + y);
OLED_WR_CMD(((x & 0xf0) >> 4) | 0x10);
OLED_WR_CMD(x & 0x0f);
}
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t Char_Size, uint8_t Color_Turn)
{
unsigned char c = 0, i = 0;
c = chr - ' ';
if (x > 128 - 1)
{
x = 0;
y = y + 2;
}
if (Char_Size == 16)
{
OLED_Set_Pos(x, y);
for (i = 0; i < 8; i++)
{
if (Color_Turn)
OLED_WR_DATA(~F8X16[c * 16 + i]);
else
OLED_WR_DATA(F8X16[c * 16 + i]);
}
OLED_Set_Pos(x, y + 1);
for (i = 0; i < 8; i++)
{
if (Color_Turn)
OLED_WR_DATA(~F8X16[c * 16 + i + 8]);
else
OLED_WR_DATA(F8X16[c * 16 + i + 8]);
}
}
else
{
OLED_Set_Pos(x, y);
for (i = 0; i < 6; i++)
{
if (Color_Turn)
OLED_WR_DATA(~F6x8[c][i]);
else
OLED_WR_DATA(F6x8[c][i]);
}
}
}
oled显示代码主要是依靠这几个函数,OLED_WR_CMD()是向设备写控制命令,是通过HAL_I2C_Mem_Write()向oled的指定地址写控制命令。OLED_WR_DATA()是向设备写控制数据。OLED_Set_Pos()是坐标设置。OLED_ShowChar()则是在oled上显示一个字符,函数的作用是根据提供的参数,在指定位置显示一个字符,并支持两种不同大小的字符显示。它会判断字符是否超出屏幕边界,并根据颜色开关来选择是否反转显示的颜色。
四、活动总结
本次项目使用kicad绘制了STM32WB55CEU6的一个四层板,正常简单验证下板卡的工作状态是否正常,之后会进行学习STM32WB无线系列的特性,如低功耗蓝牙、Zigbee等等。这次学习依然有很多不足之处和疑惑之处,后面还需要时间进行开发优化。这次活动对我来说是一次珍贵的机会,让我得以接触并了解一些平时难以触及的新工具。这次经历对我有着极大的帮助,感谢举办方!
