TI MSPM0G3507开发板驱动0.96寸SSD1306 SPI OLED屏移植实战

TI MSPM0G3507开发板驱动0.96寸SSD1306 SPI OLED屏移植实战 TI MSPM0G3507开发板驱动0.96寸SSD1306 SPI OLED屏移植实战最近在准备一个电赛项目用到了TI的MSPM0G3507这块板子需要接一个小屏幕来显示数据。我手头正好有一块中景园的0.96寸OLED屏驱动芯片是SSD1306通信方式是SPI。网上找了一圈发现针对这块新板子的现成驱动不多于是决定自己动手移植一个。整个过程踩了一些坑也总结了不少经验今天就把从零开始手把手把屏幕驱动移植到MSPM0G3507上的完整过程分享给大家希望能帮到同样在折腾这块板子的朋友。1. 准备工作了解屏幕与获取资料在开始写代码之前咱们得先把手头的硬件和软件资料搞清楚。1.1 认识0.96寸SPI OLED屏我用的这块屏幕是中景园电子的0.96寸OLED模块核心信息如下驱动芯片SSD1306。这是一款非常流行的单色OLED驱动芯片控制逻辑比较成熟。通信协议SPI串行外设接口。这意味着我们只需要几根线时钟、数据、片选等就能和MCU通信比并口节省大量IO。分辨率128 x 64 像素。虽然不大但显示些文字、简单图形或数据绰绰有余。工作电压3.3V。这一点非常重要MSPM0G3507开发板的IO电平也是3.3V可以直接连接无需电平转换。引脚数量7 Pin (2.54mm间距排针)。具体每个引脚的作用我们后面接线时会详细说。注意购买链接和资料下载链接因平台规则不便直接提供大家可以根据屏幕型号“中景园0.96寸OLED SSD1306”自行搜索。通常卖家会提供资料包里面包含驱动程序、字库和示例代码这是我们移植的基础。1.2 建立工程与导入源码拿到屏幕的资料包后里面一般会有一个针对STM32或其他常见MCU的示例工程。我们的任务就是把这个工程里的OLED驱动代码“搬”到我们的MSPM0工程里。创建/打开你的MSPM0工程。你可以使用TI官方例程中的“empty”工程作为模板这样最干净。找到驱动文件。在资料包里通常会有oled.c和oled.h这两个核心文件以及bmp.h图片字库、sys.h、delay.h等辅助文件。复制文件。在你的MSPM0工程目录下找一个合适的地方存放这些文件。我习惯在工程根目录下创建一个BSP(板级支持包) 文件夹然后把oled.c、oled.h、bmp.h复制进去。将文件添加到工程。在Code Composer Studio (CCS) 或你使用的IDE中将这些.c文件添加到工程的编译路径中并在main.c里包含oled.h头文件。2. 硬件连接把屏幕接到开发板上接线是第一步接错了后面全白搭。这块SPI屏幕有7个引脚我们需要在MSPM0G3507开发板上找到对应的GPIO引脚连接起来。根据屏幕的引脚定义和MSPM0G3507的引脚功能我选择了如下连接方式。选择这些引脚主要是考虑到它们支持SPI功能且布局相对集中方便布线。屏幕引脚功能说明MSPM0G3507连接引脚GND电源地开发板上的任一GNDVCC电源正 (3.3V)开发板上的3.3V输出SCL (D0)SPI时钟线 (SCK)PB9SDA (D1)SPI数据线 (MOSI)PB8RES复位引脚 (低电平有效)PB10(普通GPIO)DC数据/命令选择引脚PB11(普通GPIO)CS片选引脚 (低电平有效)PB14(普通GPIO)提示RES、DC、CS这三个引脚不参与SPI通信只是普通的控制信号所以用任何空闲的GPIO都可以。我选择PB10、PB11、PB14是为了和SPI引脚PB8 PB9保持在同一组GPIOB组管理起来方便。3. 软件配置使用SysConfig图形化配引脚TI的MSPM0系列有一个超好用的工具——SysConfig系统配置器。我们可以用图形化的方式来配置引脚功能和SPI外设不用再手动去查寄存器了。在CCS工程中双击打开*.syscfg文件例如empty.syscfg。配置GPIO引脚点击ADD按钮添加一个GPIO配置项。我们需要配置3个GPIORES、DC、CS。根据上面的接线表分别配置PB10、PB11、PB14为普通的输出引脚GPIO Output。你可以给它们起个容易识别的名字比如OLED_RES、OLED_DC、OLED_CS。配置SPI外设再次点击ADD添加一个SPI配置项。选择SPI作为主机Controller模式。在Pin Configuration中将SCK引脚分配给PB9将MOSI引脚分配给PB8。我们的屏幕是SPI从机只需要主机发送数据所以MISO引脚可以不用管。其他SPI参数如时钟极性CPOL、时钟相位CPHA、数据位宽、波特率等需要根据SSD1306驱动芯片的数据手册来定。对于大多数SSD1306的SPI例程常用模式是CPOL0 CPHA0模式0。波特率可以先设一个保守值比如1MHz。给这个SPI实例也起个名比如SPI_OLED。按下CtrlS保存配置。SysConfig会自动生成对应的C代码头文件通常是ti_msp_dl_config.h里面包含了所有我们刚才配置的引脚和SPI的宏定义。4. 代码移植修改驱动适配MSPM0这是最核心的一步。原来的驱动代码是为其他平台如STM32写的我们需要修改其中关于GPIO控制和SPI通信的部分使其适配MSPM0的驱动库DriverLib。4.1 修改头文件依赖和引脚定义首先修改oled.h文件。原文件可能包含了类似sys.h的头文件我们需要将其替换为MSPM0工程对应的头文件并重新定义引脚控制宏。找到oled.h中关于引脚定义的部分将其修改为如下内容。这里的宏定义直接调用TI DriverLib的GPIO控制函数操作我们之前在SysConfig里配置好的引脚。//-----------------OLED端口定义---------------- #include “board.h” // 替换原来的 sys.h board.h 会包含 ti_msp_dl_config.h // 假设你在SysConfig中将PB10、PB11、PB14分别命名为 OLED_RES、OLED_DC、OLED_CS // 这些引脚所在的端口和引脚号已经在 ti_msp_dl_config.h 中定义好了 // 我们直接使用 DL_GPIO 库函数来控制它们 #define OLED_RES_Clr() DL_GPIO_clearPins(OLED_PORT, OLED_RES_PIN) //RES 拉低 #define OLED_RES_Set() DL_GPIO_setPins(OLED_PORT, OLED_RES_PIN) //RES 拉高 #define OLED_DC_Clr() DL_GPIO_clearPins(OLED_PORT, OLED_DC_PIN) //DC 拉低表示发送命令 #define OLED_DC_Set() DL_GPIO_setPins(OLED_PORT, OLED_DC_PIN) //DC 拉高表示发送数据 #define OLED_CS_Clr() DL_GPIO_clearPins(OLED_PORT, OLED_CS_PIN) //CS 拉低选中屏幕 #define OLED_CS_Set() DL_GPIO_setPins(OLED_PORT, OLED_CS_PIN) //CS 拉高取消选中4.2 重写核心通信函数OLED_WR_ByteSPI通信是驱动屏幕的关键。原驱动中的OLED_WR_Byte函数通常包含了模拟SPI或硬件SPI的底层操作。我们需要将其改为使用MSPM0的硬件SPI。在oled.c文件中找到OLED_WR_Byte(u8 dat, u8 cmd)函数将其替换为以下内容void OLED_WR_Byte(u8 dat, u8 cmd) { // 1. 设置DC引脚电平决定发送的是命令还是数据 if(cmd) OLED_DC_Clr(); // DC0写命令 else OLED_DC_Set(); // DC1写数据 // 2. 拉低片选CS选中OLED设备 OLED_CS_Clr(); // 3. 使用DriverLib的SPI函数发送一个字节数据 // SPI_OLED_INST 是在SysConfig中定义的SPI实例句柄在 ti_msp_dl_config.h 中声明 DL_SPI_transmitData8(SPI_OLED_INST, dat); // 4. 等待SPI发送完成非阻塞发送需要等待 while(DL_SPI_isBusy(SPI_OLED_INST)); // 5. 拉高片选CS结束本次传输 OLED_CS_Set(); // 可选将DC置为默认高电平数据状态 OLED_DC_Set(); }这个函数是屏幕驱动的“心脏”它负责把每一个字节的命令或数据通过硬件SPI发送给SSD1306芯片。DL_SPI_transmitData8是TI DriverLib提供的API用于发送8位数据。4.3 修改初始化函数OLED_Init原驱动的OLED_Init函数里可能包含了对GPIO模式的初始化比如设置推挽输出等。因为我们已经在SysConfig中图形化配置好了GPIO并且DriverLib的初始化函数SYSCFG_DL_init()会帮我们完成所有外设的初始化所以可以删除OLED_Init函数开头关于GPIO模式初始化的代码。通常只需要保留对RES复位引脚的操作和那一长串SSD1306初始化命令序列即可。确保OLED_Init函数开头是这样的void OLED_Init(void) { // 硬件复位OLED OLED_RES_Clr(); // RES拉低 delay_ms(200); // 保持低电平一段时间 OLED_RES_Set(); // RES拉高结束复位 delay_ms(200); // 等待屏幕内部初始化 // 接下来是发送一系列初始化命令这部分代码通常不需要改动 OLED_WR_Byte(0xAE, OLED_CMD); // 关闭显示 OLED_WR_Byte(0x00, OLED_CMD); // 设置低列地址 OLED_WR_Byte(0x10, OLED_CMD); // 设置高列地址 OLED_WR_Byte(0x40, OLED_CMD); // 设置起始行地址 // ... 后续初始化命令保持不变 OLED_Clear(); OLED_WR_Byte(0xAF, OLED_CMD); // 开启显示 }注意delay_ms函数需要你自己实现或者使用DriverLib提供的延时函数。你可以用一个简单的循环延时或者配置一个定时器来获得精确延时。5. 功能验证编写测试主程序所有代码修改完成后就该上电测试了。我们在main.c里写一个简单的测试程序。#include “ti_msp_dl_config.h” #include “board.h” #include “oled.h” #include “bmp.h” // 包含字库和图片数据 int main(void) { // 初始化所有在SysConfig中配置的外设GPIO SPI等 SYSCFG_DL_init(); // 初始化OLED屏幕 OLED_Init(); OLED_ColorTurn(0); // 0正常显示1 反色显示 OLED_DisplayTurn(0); // 0正常显示 1 屏幕翻转显示 while(1) { // 测试1显示一张图片如果bmp.h里有图片数据的话 // OLED_ShowPicture(0, 0, 128, 64, BMP1, 1); // OLED_Refresh(); // delay_ms(1000); // OLED_Clear(); // 测试2显示汉字和字符串 OLED_ShowChinese(0, 0, 0, 16, 1); // 在(0,0)位置显示16x16的0号汉字 OLED_ShowString(20, 16, “Hello MSPM0!”, 16, 1); OLED_Refresh(); delay_ms(2000); OLED_Clear(); // 测试3显示ASCII字符和数字 OLED_ShowString(0, 32, “Count:”, 16, 1); for(int i0; i100; i){ OLED_ShowNum(60, 32, i, 3, 16, 1); // 在(60,32)显示3位数字i OLED_Refresh(); delay_ms(100); } OLED_Clear(); } }将工程编译后下载到MSPM0G3507开发板并给屏幕上电。如果一切顺利你应该能看到屏幕上依次显示出汉字、英文和递增的数字。如果屏幕没有显示别着急这是调试的常态。首先检查硬件连接是否牢固电源和地有没有接反。然后用逻辑分析仪或者示波器抓一下SPI的SCK和MOSI引脚看看在调用OLED_WR_Byte时是否有波形输出。如果没有波形检查SPI配置是否正确如果有波形但屏幕不亮检查初始化命令序列、DC和RES引脚的控制时序是否正确。这个移植过程最关键的就是理解原有驱动框架然后将底层硬件相关的操作GPIO和SPI替换成目标平台MSPM0的库函数。一旦打通了通信剩下的显示功能就都是上层应用可以尽情发挥了。希望这篇实战指南能让你顺利点亮手中的小屏幕。