Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
国民技术_N32G45x
RT-Thread活动
【N32G457 】基于RT-Thread和N32G457的温度气压显示系统
发布于 2022-04-05 22:21:24 浏览:849
订阅该版
此次基于RTT和N32G457开发实现u8g2 spi 硬件驱动显示及bmp280 传感器驱动。 整体架构如下: ![image.png](https://oss-club.rt-thread.org/uploads/20220405/4e5af5ac51452b0657e9d2fd7fe37956.png) ![image.png](https://oss-club.rt-thread.org/uploads/20220405/b113522fb7d6c8eeedb795ad3873c36a.png.webp) N32G457这个款MCU性能还是比较强悍的,基本外设都有,主频相对高,支持fpu,可以满足使用需求,在此记录下开发过程 1.环境搭建 板载的daplink 需要使用inf 重新安装驱动才能使用(安装驱动需要禁用签名) 发现更新RTT studio 版本后无法使用,之前有概率使用不成功。后续索性不使用板载link,掏出我珍藏许久的stlink 和usb转ttl串口。 pyocd 及msh 正常使用 ![image.png](https://oss-club.rt-thread.org/uploads/20220405/20fbc87162560353f34d8b60ac6133d2.png) 此处断开,使用外部stlink 连接,使用外部串口助手 2.oled 显示实现 使用n32g457 的 1.0.2 rtt驱动,发现并未有drv_spi 实现,后续参考 https://gitee.com/balanceTWK/n32g452xx_-lvgl,移植drv_spi.c drv_spi.h ``` /* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2022-04-04 lenovo the first version */ #include
#include
#include
#ifdef RT_USING_SPI #ifdef BSP_USING_SPI #if defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) || defined(BSP_USING_SPI3) || defined(BSP_USING_SPI4) || defined(BSP_USING_SPI5) || defined(BSP_USING_SPI6) #include "drv_spi.h" #define DRV_DEBUG #define LOG_TAG "drv.spi" #include
enum { #ifdef BSP_USING_SPI1 SPI1_INDEX, #endif #ifdef BSP_USING_SPI2 SPI2_INDEX, #endif #ifdef BSP_USING_SPI3 SPI3_INDEX, #endif #ifdef BSP_USING_SPI4 SPI4_INDEX, #endif #ifdef BSP_USING_SPI5 SPI5_INDEX, #endif #ifdef BSP_USING_SPI6 SPI6_INDEX, #endif }; struct n32_spi_config { SPI_Module *module; char *bus_name; }; /* n32 spi dirver class */ struct n32_spi { SPI_InitType SPI_InitStructure; struct n32_spi_config *config; struct rt_spi_configuration *cfg; struct rt_spi_bus spi_bus; }; static struct n32_spi_config spi_config[] = { #ifdef BSP_USING_SPI1 { .module = SPI1, .bus_name = "spi1", }, #endif #ifdef BSP_USING_SPI2 { .module = SPI2, .bus_name = "spi2", }, #endif #ifdef BSP_USING_SPI3 { .module = SPI3, .bus_name = "spi3", }, #endif }; static struct n32_spi spi_bus_obj[sizeof(spi_config) / sizeof(spi_config[0])] = {0}; static rt_err_t n32_spi_init(struct n32_spi *spi_drv, struct rt_spi_configuration *cfg) { RT_ASSERT(spi_drv != RT_NULL); RT_ASSERT(cfg != RT_NULL); SPI_InitType *SPI_InitStructure = &spi_drv->SPI_InitStructure; /* GPIO configuration ------------------------------------------------------*/ n32_msp_spi_init(spi_drv->config->module); if (cfg->mode & RT_SPI_SLAVE) { /* SPI_InitStructure->SpiMode = SPI_MODE_SLAVE; */ return RT_ERROR; } else { SPI_InitStructure->SpiMode = SPI_MODE_MASTER; } if (cfg->mode & RT_SPI_3WIRE) { SPI_InitStructure->DataDirection = SPI_DIR_SINGLELINE_TX; } else { SPI_InitStructure->DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX; } if (cfg->data_width == 8) { SPI_InitStructure->DataLen = SPI_DATA_SIZE_8BITS; } else if (cfg->data_width == 16) { SPI_InitStructure->DataLen = SPI_DATA_SIZE_16BITS; } else { return RT_EIO; } if (cfg->mode & RT_SPI_CPHA) { SPI_InitStructure->CLKPHA = SPI_CLKPHA_SECOND_EDGE; } else { SPI_InitStructure->CLKPHA = SPI_CLKPHA_FIRST_EDGE; } if (cfg->mode & RT_SPI_CPOL) { SPI_InitStructure->CLKPOL = SPI_CLKPOL_HIGH; } else { SPI_InitStructure->CLKPOL = SPI_CLKPOL_LOW; } if (cfg->mode & RT_SPI_NO_CS) { SPI_InitStructure->NSS = SPI_NSS_HARD; } else { SPI_InitStructure->NSS = SPI_NSS_SOFT; } /* TODO */ /* uint32_t SPI_APB_CLOCK; if (cfg->max_hz >= SPI_APB_CLOCK / 2) { SPI_InitStructure->BaudRatePres = SPI_BAUDRATEPRESCALER_2; } */ SPI_InitStructure->BaudRatePres = SPI_BR_PRESCALER_4; if (cfg->mode & RT_SPI_MSB) { SPI_InitStructure->FirstBit = SPI_FB_MSB; } else { SPI_InitStructure->FirstBit = SPI_FB_LSB; } SPI_InitStructure->CRCPoly = 7; SPI_Init(spi_drv->config->module, SPI_InitStructure); /* Enable SPI_MASTER TXE interrupt */ SPI_I2S_EnableInt(spi_drv->config->module, SPI_I2S_INT_TE, ENABLE); /* Enable SPI_MASTER */ SPI_Enable(spi_drv->config->module, ENABLE); return RT_EOK; } static rt_err_t spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration) { RT_ASSERT(device != RT_NULL); RT_ASSERT(configuration != RT_NULL); struct n32_spi *spi_drv = rt_container_of(device->bus, struct n32_spi, spi_bus); spi_drv->cfg = configuration; return n32_spi_init(spi_drv, configuration); } static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message) { rt_size_t message_length, already_length; rt_uint8_t *recv_buf; const rt_uint8_t *send_buf; RT_ASSERT(device != RT_NULL); RT_ASSERT(device->bus != RT_NULL); RT_ASSERT(device->bus->parent.user_data != RT_NULL); RT_ASSERT(message != RT_NULL); struct n32_spi *spi_drv = rt_container_of(device->bus, struct n32_spi, spi_bus); struct n32_hw_spi_cs *cs = device->parent.user_data; if (message->cs_take && !(device->config.mode & RT_SPI_NO_CS)) { if (device->config.mode & RT_SPI_CS_HIGH) GPIO_SetBits(cs->module, cs->pin); else GPIO_ResetBits(cs->module, cs->pin); } message_length = message->length; recv_buf = message->recv_buf; send_buf = message->send_buf; for (already_length = 0; already_length < message_length; ) { /* start once data exchange in DMA mode */ if (message->send_buf && message->recv_buf) { LOG_D("%s:%d",__FUNCTION__,__LINE__); } else if (message->send_buf) { /* Wait for SPIy Tx buffer empty */ while (SPI_I2S_GetStatus(spi_drv->config->module, SPI_I2S_TE_FLAG) == RESET); SPI_I2S_TransmitData(spi_drv->config->module, (send_buf[already_length])); } else { /* Wait for SPIy data reception */ while (SPI_I2S_GetStatus(spi_drv->config->module, SPI_I2S_RNE_FLAG) == RESET); /* Read SPIy received data */ recv_buf[already_length] = (rt_uint8_t)SPI_I2S_ReceiveData(spi_drv->config->module); } already_length ++; } if (message->cs_release && !(device->config.mode & RT_SPI_NO_CS)) { if (device->config.mode & RT_SPI_CS_HIGH) GPIO_ResetBits(cs->module, cs->pin); else GPIO_SetBits(cs->module, cs->pin); } return message->length; } static const struct rt_spi_ops n32_spi_ops = { .configure = spi_configure, .xfer = spixfer, }; static int rt_hw_spi_bus_init(void) { rt_err_t result; for (int i = 0; i < sizeof(spi_config) / sizeof(spi_config[0]); i++) { spi_bus_obj[i].config = &spi_config[i]; spi_bus_obj[i].spi_bus.parent.user_data = &spi_config[i]; result = rt_spi_bus_register(&spi_bus_obj[i].spi_bus, spi_config[i].bus_name, &n32_spi_ops); RT_ASSERT(result == RT_EOK); LOG_D("%s bus init done", spi_config[i].bus_name); } return result; } int rt_hw_spi_init(void) { /* TODO: n32_get_dma_info(); */ return rt_hw_spi_bus_init(); } INIT_BOARD_EXPORT(rt_hw_spi_init); /** * Attach the spi device to SPI bus, this function must be used after initialization. */ rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, GPIO_Module *cs_gpiox, uint32_t cs_gpio_pin) { rt_err_t result; struct rt_spi_device *spi_device; struct n32_hw_spi_cs *cs_pin; GPIO_InitType GPIO_InitStructure; RT_ASSERT(bus_name != RT_NULL); RT_ASSERT(device_name != RT_NULL); /* Enable the GPIO Clock */ if (cs_gpiox == GPIOA) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); } else if (cs_gpiox == GPIOB) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); } else if (cs_gpiox == GPIOC) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); } else if (cs_gpiox == GPIOD) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE); } else if (cs_gpiox == GPIOE) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE); } else if (cs_gpiox == GPIOF) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOF, ENABLE); } else if (cs_gpiox == GPIOG) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOG, ENABLE); } /* Configure the GPIO pin */ if (cs_gpio_pin <= GPIO_PIN_ALL) { GPIO_InitStructure.Pin = cs_gpio_pin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitPeripheral(cs_gpiox, &GPIO_InitStructure); } /* attach the device to spi bus*/ spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device)); RT_ASSERT(spi_device != RT_NULL); cs_pin = (struct n32_hw_spi_cs *)rt_malloc(sizeof(struct n32_hw_spi_cs)); RT_ASSERT(cs_pin != RT_NULL); cs_pin->module = cs_gpiox; cs_pin->pin = cs_gpio_pin; result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin); if (result != RT_EOK) { LOG_E("%s attach to %s faild, %d\n", device_name, bus_name, result); } RT_ASSERT(result == RT_EOK); LOG_D("%s attach to %s done", device_name, bus_name); return result; } #endif /* BSP_USING_SPIx */ #endif /* BSP_USING_SPI */ #endif /* RT_USING_SPI */ ``` RTT setting 中开启spi iic 及spi1 添加u8g2 bmp280 等库 ![image.png](https://oss-club.rt-thread.org/uploads/20220405/bbdad6bbc2b33d455479f0e9fcc4ffb8.png.webp) 配置u8g2 信息 ![image.png](https://oss-club.rt-thread.org/uploads/20220405/fb9274d5f540052622e65daf598860af.png) 根据库的demo 初始化 u8g2 ``` u8g2_t u8g2; u8g2_Setup_ssd1306_128x64_noname_f( &u8g2, U8G2_R0, u8x8_byte_rtthread_4wire_hw_spi, u8x8_gpio_and_delay_rtthread); u8x8_SetPin(u8g2_GetU8x8(&u8g2), U8X8_PIN_CS, OLED_SPI_PIN_CS); u8x8_SetPin(u8g2_GetU8x8(&u8g2), U8X8_PIN_DC, OLED_SPI_PIN_DC); u8x8_SetPin(u8g2_GetU8x8(&u8g2), U8X8_PIN_RESET, OLED_SPI_PIN_RES); u8g2_InitDisplay(&u8g2); u8g2_SetPowerSave(&u8g2, 0); ``` 这里使用的管脚是 #define OLED_SPI_PIN_RES 33 // PC4 #define OLED_SPI_PIN_DC 34 //PC5 #define OLED_SPI_PIN_CS 29 // PA4 宏定义查找可使用群里这位网友提供的excel ,使用起来相当方便 [641978584d612c84016db2be7571f61a.xlsx](https://oss-club.rt-thread.org/uploads/20220405/641978584d612c84016db2be7571f61a.xlsx) u8g2 初始化 显示 ``` // Draw Graphics /* full buffer example, setup procedure ends in _f */ u8g2_ClearBuffer(&u8g2); u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr); //u8g2_SetFont(&u8g2,u8g2_font_unifont_t_chinese2); u8g2_DrawStr(&u8g2, 1, 18, "BMP280 demo"); //u8g2_DrawUTF8(&u8g2, 12,0, "你好"); u8g2_SendBuffer(&u8g2); ``` 2.bmp280 驱动 bmp280整体架构 ![image.png](https://oss-club.rt-thread.org/uploads/20220405/2c84cbafec33c73bd43c87fdcbcce089.png.webp) rttseting 内添加bmp280 设置iic 驱动,驱动地址0x67,使用iic 软件驱动,软件管脚为92 93 ``` #define BMP280_ADDR_DEFAULT BMP280_I2C_ADDR_PRIM #define BMP280_I2CBUS_NAME "i2c1" ``` 初始化过程 ``` #define BMP_NAME "bmp280" int bmp280_port(void) { struct rt_sensor_config cfg; cfg.intf.dev_name = BMP280_I2CBUS_NAME; cfg.intf.user_data = (void *)BMP280_ADDR_DEFAULT; rt_hw_bmp280_init(BMP_NAME, &cfg); return 0; } INIT_APP_EXPORT(bmp280_port); ``` 驱动正常后,可在list_device 中显示 3.oled显示传感器信息 bmp280 注册时使用两个设备名 ``` #define BMP_TEMP "temp_bmp280" #define BMP_BARO "baro_bmp280" ``` 所以获取数据前先进行设备查找、打开、获取参数频率 ``` rt_device_t temp_dev =RT_NULL; rt_device_t baro_dev =RT_NULL; rt_size_t res =0; temp_dev = rt_device_find(BMP_TEMP); if(temp_dev == RT_NULL) { rt_kprintf("can not find bmp280 temp\n"); return ; } baro_dev = rt_device_find(BMP_BARO); if(temp_dev == RT_NULL) { rt_kprintf("can not find bmp280 baro\n"); return ; } if (rt_device_open(temp_dev, RT_DEVICE_FLAG_RDWR) != RT_EOK) { rt_kprintf("open device failed!\n"); return; } if (rt_device_open(baro_dev, RT_DEVICE_FLAG_RDWR) != RT_EOK) { rt_kprintf("open device failed!\n"); return; } rt_device_control(temp_dev, RT_SENSOR_CTRL_SET_ODR, (void *)100); rt_device_control(baro_dev, RT_SENSOR_CTRL_SET_ODR, (void *)100); ``` 在oled 显示线程中进行数据读取,并通过U8g2将更新的数据显示在oled上 ``` res = rt_device_read(temp_dev, 0, &temp_data, 1); if (res != 1) { rt_kprintf("read data failed!size is %d\n", res); rt_device_close(temp_dev); return; } #if 0 else { rt_kprintf("temp:%3d.%d C\n", temp_data.data.temp /10 , temp_data.data.temp %10); } #endif res = rt_device_read(baro_dev, 0, &baro_data, 1); if (res != 1) { rt_kprintf("read data failed!size is %d\n", res); rt_device_close(baro_dev); return; } #if 0 else { rt_kprintf("baro:%d Pa\n",baro_data.data.baro); } #endif u8g2_ClearBuffer(&u8g2); u8g2_DrawStr(&u8g2, 10, 18, "BMP280 demo"); sprintf(buf,"temp:%d.%d C",temp_data.data.temp /10,temp_data.data.temp %10); u8g2_DrawStr(&u8g2, 32, 40, buf); sprintf(buf,"baro:%d Pa",baro_data.data.baro ); u8g2_DrawStr(&u8g2, 32, 56, buf); u8g2_SendBuffer(&u8g2); rt_thread_mdelay(100); ``` 开源地址 https://gitee.com/xinshuwei/n32g457_iot 实现效果见附件 [n32g457.mp4](https://oss-club.rt-thread.org/uploads/20220405/d3488e57234ec0536d30eb7deccc8f61.mp4) 桌面效果图 ![1.jpg](https://oss-club.rt-thread.org/uploads/20220405/4b17c3bee1e4e2ac9eebc5b72db52878.jpg) 感谢社区伙伴支持及小师弟的帮助
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
xinshuwei
这家伙很懒,什么也没写!
文章
8
回答
0
被采纳
0
关注TA
发私信
相关文章
1
(苏州站)RT-Thread物联网开发者沙龙【已结束】
2
(成都站)RT-Thread物联网开发者沙龙
3
(深圳站)RT-Thread物联网开发者沙龙
4
(西安站)RT-Thread物联网开发者沙龙
5
成都站2018 RT-Thread开发者沙龙回顾及PPT下载
6
2018 RT-Thread物联网开发者沙龙(北京站)
7
2018 RT-Thread物联网开发者沙龙(南京站)
8
第十三届研电赛RT-Thread企业专项奖发布通知
9
RT-Thread应用作品征集大赛开始啦!
10
你的投票将决定RT-Thread官网应该优先准备的文档是哪些
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
cubemx
WIZnet_W5500
ota在线升级
PWM
BSP
flash
freemodbus
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
keil_MDK
ulog
SFUD
msh
C++_cpp
MicroPython
本月问答贡献
RTT_逍遥
7
个答案
2
次被采纳
三世执戟
7
个答案
1
次被采纳
KunYi
6
个答案
1
次被采纳
winfeng
2
个答案
1
次被采纳
chenyaxing
2
个答案
1
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
3
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部