首页 > 评测 > RTT-Studio环境下的APM32外设驱动使用指南
RTT-Studio环境下的APM32外设驱动使用指南
- [导读]
- 本帖最后由 luobeihai 于 2023-4-19 00:08 编辑 #申请原创# @21小跑堂 1. 简介由于自己平时在项目中经常使用 APM32 系列的 MCU,而且经常是和 RT-Thread 系统一起使用,慢慢的就对 APM32 系列 MCU 的
本帖最后由 luobeihai 于 2023-4-19 00:08 编辑
#申请原创# @21小跑堂
1. 简介
2. 新建RTT-Studio工程
2.1 下载APM32F4软件支持包
2.2 基于芯片新建一个 APM32F407 的工程
3. apm32_msp.c 文件介绍
4. UART设备
4.1 确定串口引脚,修改串口GPIO初始化代码
- void apm32_usart_init(void)
- {
- GPIO_Config_T GPIO_ConfigStruct;
- #ifdef BSP_USING_UART6
- RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOC);
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_USART6);
- GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_6, GPIO_AF_USART6);
- GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_7, GPIO_AF_USART6);
- GPIO_ConfigStruct.pin = GPIO_PIN_6 | GPIO_PIN_7;
- GPIO_ConfigStruct.mode = GPIO_MODE_AF;
- GPIO_ConfigStruct.otype = GPIO_OTYPE_PP;
- GPIO_ConfigStruct.pupd = GPIO_PUPD_UP;
- GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
- GPIO_Config(GPIOC, &GPIO_ConfigStruct);
- #endif
- }
4.2 在board.h中修改UART端口号
4.3 在 rtconfig.h 文件中修改控制台所需要的串口设备
5. ADC设备
5.1 使能ADC外设驱动
5.2 在board.h文件中定义ADC宏
5.3 ADC设备测试方法
- adc probe <adc_name> - probe adc by name
- adc read <channel> - read adc value on the channel
- adc disable <channel> - disable adc channel
- adc enable <channel> - enable adc channel
6. PWM设备
6.1 使能PWM外设驱动
6.2 在board.h文件中定义PWM外设相关的宏
6.3 在apm32_msp.c文件中添加定时器通道初始化代码
- void apm32_msp_timer_init(void *Instance)
- {
- #ifdef BSP_USING_PWM3
- GPIO_Config_T gpio_config;
- TMR_T *tmr_x = (TMR_T *)Instance;
- if (tmr_x == TMR3)
- {
- RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOC);
- RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR3);
- /* TMR3 channel 1 gpio init */
- GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_6, GPIO_AF_TMR3);
- gpio_config.pin = GPIO_PIN_6;
- gpio_config.mode = GPIO_MODE_AF;
- gpio_config.otype = GPIO_OTYPE_PP;
- gpio_config.speed = GPIO_SPEED_50MHz;
- GPIO_Config(GPIOC, &gpio_config);
- /* TMR3 channel 2 gpio init */
- GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_7, GPIO_AF_TMR3);
- gpio_config.pin = GPIO_PIN_7;
- GPIO_Config(GPIOC, &gpio_config);
- /* TMR3 channel 3 gpio init */
- GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_8, GPIO_AF_TMR3);
- gpio_config.pin = GPIO_PIN_8;
- GPIO_Config(GPIOC, &gpio_config);
- /* TMR3 channel 4 gpio init */
- GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_9, GPIO_AF_TMR3);
- gpio_config.pin = GPIO_PIN_9;
- GPIO_Config(GPIOC, &gpio_config);
- }
- #endif
- }
6.4 PWM设备使用示例
- /*
- * 程序清单:这是一个 PWM 设备使用例程
- * 例程导出了 pwm_led_sample 命令到控制终端
- * 命令调用格式:pwm_led_sample
- * 程序功能:通过 PWM 设备控制 LED 灯的亮度,可以看到LED不停的由暗变到亮,然后又从亮变到暗。
- */
- #include <rtthread.h>
- #include <rtdevice.h>
- #define PWM_DEV_NAME "pwm3" /* PWM设备名称 */
- #define PWM_DEV_CHANNEL 4 /* PWM通道 */
- struct rt_device_pwm *pwm_dev; /* PWM设备句柄 */
- static int pwm_led_sample(int argc, char *argv[])
- {
- rt_uint32_t period, pulse, dir;
- period = 500000; /* 周期为0.5ms,单位为纳秒ns */
- dir = 1; /* PWM脉冲宽度值的增减方向 */
- pulse = 0; /* PWM脉冲宽度值,单位为纳秒ns */
- /* 查找设备 */
- pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME);
- if (pwm_dev == RT_NULL)
- {
- rt_kprintf("pwm sample run failed! can't find %s device!\n", PWM_DEV_NAME);
- return RT_ERROR;
- }
- /* 设置PWM周期和脉冲宽度默认值 */
- rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);
- /* 使能设备 */
- rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);
- while (1)
- {
- rt_thread_mdelay(50);
- if (dir)
- {
- pulse += 5000; /* 从0值开始每次增加5000ns */
- }
- else
- {
- pulse -= 5000; /* 从最大值开始每次减少5000ns */
- }
- if (pulse >= period)
- {
- dir = 0;
- }
- if (0 == pulse)
- {
- dir = 1;
- }
- /* 设置PWM周期和脉冲宽度 */
- rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);
- }
- }
- /* 导出到 msh 命令列表中 */
- MSH_CMD_EXPORT(pwm_led_sample, pwm sample);
7. SPI设备
7.1 使能SPI外设驱动和串行Flash驱动程序
7.2 在board.h文件中定义SPI相关的宏
7.3 在apm32_msp.c中编写SPI外设引脚的初始化代码
- void apm32_msp_spi_init(void *Instance)
- {
- #if defined (BSP_USING_SPI1) || defined (BSP_USING_SPI2) || defined (BSP_USING_SPI3)
- GPIO_Config_T gpioConfig;
- SPI_T *spi_x = (SPI_T *)Instance;
- if(spi_x == SPI1)
- {
- /* Enable related Clock */
- RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB);
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SPI1);
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
- /* Config SPI1 PinAF */
- GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_3, GPIO_AF_SPI1);
- GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_4, GPIO_AF_SPI1);
- GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_5, GPIO_AF_SPI1);
- /* Config SPI GPIO, SCK=PB3, MISO=PB4, MOSI=PB5 */
- GPIO_ConfigStructInit(&gpioConfig);
- gpioConfig.pin = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
- gpioConfig.speed = GPIO_SPEED_100MHz;
- gpioConfig.mode = GPIO_MODE_AF;
- gpioConfig.otype = GPIO_OTYPE_PP;
- gpioConfig.pupd = GPIO_PUPD_NOPULL;
- GPIO_Config(GPIOB, &gpioConfig);
- }
- #endif
- }
7.4 挂载SPI设备
- #include <rtthread.h>
- #include "spi_flash.h"
- #include "spi_flash_sfud.h"
- #include "drv_spi.h"
- static int rt_hw_spi_flash_init(void)
- {
- RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOG);
- rt_hw_spi_device_attach("spi1", "spi10", GPIOG, GPIO_PIN_8);
- if (RT_NULL == rt_sfud_flash_probe("W25Q128", "spi10"))
- {
- return -RT_ERROR;
- }
- return RT_EOK;
- }
- INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);
8. CAN设备
8.1 使能CAN外设驱动
8.2 在board.h定义与CAN外设相关的宏
- #define BSP_USING_CAN1
- #define BSP_USING_CAN2
8.3 在apm32_msp.c文件中编写CAN引脚初始化代码
- void apm32_msp_can_init(void *Instance)
- {
- #if defined(BSP_USING_CAN1) || defined(BSP_USING_CAN2)
- GPIO_Config_T GPIO_InitStructure;
- CAN_T *CANx = (CAN_T *)Instance;
- if (CAN1 == CANx)
- {
- RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_CAN1);
- RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB);
- /* PB8: CAN1_RX, PB9: CAN1_TX */
- GPIO_InitStructure.pin = GPIO_PIN_8 | GPIO_PIN_9;
- GPIO_InitStructure.mode = GPIO_MODE_AF;
- GPIO_InitStructure.otype = GPIO_OTYPE_PP;
- GPIO_InitStructure.speed = GPIO_SPEED_100MHz;
- GPIO_InitStructure.pupd = GPIO_PUPD_UP;
- GPIO_Config(GPIOB, &GPIO_InitStructure);
- GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_8, GPIO_AF_CAN1);
- GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_9, GPIO_AF_CAN1);
- }
- else if (CAN2 == CANx)
- {
- /* When using the CAN2 peripheral, the CAN1 clock must be turned on */
- RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_CAN1);
- RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_CAN2);
- RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB);
- /* PB12: CAN2_RX, PB13: CAN2_TX */
- GPIO_InitStructure.pin = GPIO_PIN_12 | GPIO_PIN_13;
- GPIO_InitStructure.mode = GPIO_MODE_AF;
- GPIO_InitStructure.otype = GPIO_OTYPE_PP;
- GPIO_InitStructure.speed = GPIO_SPEED_100MHz;
- GPIO_InitStructure.pupd = GPIO_PUPD_UP;
- GPIO_Config(GPIOB, &GPIO_InitStructure);
- GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_12, GPIO_AF_CAN2);
- GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_13, GPIO_AF_CAN2);
- }
- #endif
- }
8.4 CAN设备使用示例
-
首先把文档中的示例代码复制到main.c文件,然后编译下载。
-
使用CAN分析仪连接到你板子的CANH和CANL(我所使用的是创芯科技的CAN分析仪)。
-
打开创芯科技的CAN分析仪上位机软件,然后按照1M的波特率启动设备(因为CAN驱动程序默认的波特率是1M,如果你修改了CAN驱动程序中的波特率,那么CAN接收数据的上位机设置的波特率要与之对应)。
-
在串口终端运行 can_sample 这个命令。
-
然后查看 CAN 上位机工具是否接收到了开发板发送的CAN数据。
-
也可以提供CAN上位机发送数据到开发板,然后板子会把接收到的数据打印出来。
9. SDIO设备
9.1 使能SDIO外设驱动以及FatFs
9.2 在board.h文件中定义SDIO外设相关的宏
9.3 在apm32_msp.c文件中编写SDIO引脚初始化代码
- void apm32_msp_sdio_init(void *Instance)
- {
- #ifdef BSP_USING_SDIO
- GPIO_Config_T GPIO_InitStructure;
- /* Enable the GPIO Clock */
- RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOC | RCM_AHB1_PERIPH_GPIOD);
- /* Enable the SDIO Clock */
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SDIO);
- /* Enable the SDIO peripheral reset */
- RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_SDIO);
- /* Configure the GPIO pin */
- GPIO_InitStructure.pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12;
- GPIO_InitStructure.mode = GPIO_MODE_AF;
- GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
- GPIO_InitStructure.otype = GPIO_OTYPE_PP;
- GPIO_InitStructure.pupd = GPIO_PUPD_UP;
- GPIO_Config(GPIOC, &GPIO_InitStructure);
- GPIO_InitStructure.pin = GPIO_PIN_2;
- GPIO_Config(GPIOD, &GPIO_InitStructure);
- GPIO_ConfigPinAF(GPIOC,GPIO_PIN_SOURCE_8, GPIO_AF_SDIO);
- GPIO_ConfigPinAF(GPIOC,GPIO_PIN_SOURCE_9, GPIO_AF_SDIO);
- GPIO_ConfigPinAF(GPIOC,GPIO_PIN_SOURCE_10, GPIO_AF_SDIO);
- GPIO_ConfigPinAF(GPIOC,GPIO_PIN_SOURCE_11, GPIO_AF_SDIO);
- GPIO_ConfigPinAF(GPIOC,GPIO_PIN_SOURCE_12, GPIO_AF_SDIO);
- GPIO_ConfigPinAF(GPIOD,GPIO_PIN_SOURCE_2, GPIO_AF_SDIO);
- /* Disable the SDIO peripheral reset */
- RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_SDIO);
- #endif
- }
9.4 SD卡挂载elm FatFs文件系统
- #include <dfs_elm.h>
- #include <dfs_fs.h>
- #include <dfs_file.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <sys/stat.h>
- #include <sys/statfs.h>
- void sd_mount(void *parameter)
- {
- while (1)
- {
- rt_thread_mdelay(500);
- if(rt_device_find("sd0") != RT_NULL)
- {
- if (dfs_mount("sd0", "/", "elm", 0, 0) == RT_EOK)
- {
- LOG_I("sd card mount to '/'");
- break;
- }
- else
- {
- LOG_W("sd card mount to '/' failed!");
- }
- }
- }
- }
- int apm32_sdcard_mount(void)
- {
- rt_thread_t tid;
- tid = rt_thread_create("sd_mount", sd_mount, RT_NULL,
- 2048, RT_THREAD_PRIORITY_MAX - 2, 20);
- if (tid != RT_NULL)
- {
- rt_thread_startup(tid);
- }
- else
- {
- LOG_E("create sd_mount thread err!");
- }
- return RT_EOK;
- }
- INIT_APP_EXPORT(apm32_sdcard_mount);
10. ETH设备
10.1 使能LwIP堆栈
10.2 在board.h中定义以太网相关的宏
10.3 在apm32_msp.c文件中添加ETH外设初始化代码
- void apm32_msp_eth_init(void *Instance)
- {
- #ifdef BSP_USING_ETH
- GPIO_Config_T GPIO_ConfigStruct;
- /* Enable SYSCFG clock */
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
- /* Enable GPIOs clocks */
- RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA | RCM_AHB1_PERIPH_GPIOC | RCM_AHB1_PERIPH_GPIOG);
- /* MII/RMII Media interface selection */
- SYSCFG_ConfigMediaInterface(SYSCFG_INTERFACE_RMII);
- /*********************** Ethernet pins configuration ***************************/
- /*
- ETH_MDIO -------------------------> PA2
- ETH_MDC --------------------------> PC1
- ETH_MII_RX_CLK/ETH_RMII_REF_CLK---> PA1
- ETH_MII_RX_DV/ETH_RMII_CRS_DV ----> PA7
- ETH_MII_RXD0/ETH_RMII_RXD0 -------> PC4
- ETH_MII_RXD1/ETH_RMII_RXD1 -------> PC5
- ETH_MII_TX_EN/ETH_RMII_TX_EN -----> PG11
- ETH_MII_TXD0/ETH_RMII_TXD0 -------> PG13
- ETH_MII_TXD1/ETH_RMII_TXD1 -------> PG14
- */
- /* Configure PC1, PC4 and PC5 */
- GPIO_ConfigStruct.pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
- GPIO_ConfigStruct.speed = GPIO_SPEED_100MHz;
- GPIO_ConfigStruct.mode = GPIO_MODE_AF;
- GPIO_ConfigStruct.otype = GPIO_OTYPE_PP;
- GPIO_ConfigStruct.pupd = GPIO_PUPD_NOPULL;
- GPIO_Config(GPIOC, &GPIO_ConfigStruct);
- GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_1, GPIO_AF_ETH);
- GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_4, GPIO_AF_ETH);
- GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_5, GPIO_AF_ETH);
- /* Configure PG11, PG13 and PG14 */
- GPIO_ConfigStruct.pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
- GPIO_Config(GPIOG, &GPIO_ConfigStruct);
- GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_11, GPIO_AF_ETH);
- GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_13, GPIO_AF_ETH);
- GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_14, GPIO_AF_ETH);
- /* Configure PA1, PA2 and PA7 */
- GPIO_ConfigStruct.pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
- GPIO_Config(GPIOA, &GPIO_ConfigStruct);
- GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_1, GPIO_AF_ETH);
- GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_2, GPIO_AF_ETH);
- GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_7, GPIO_AF_ETH);
- #endif
- }
10.4 添加 phy 芯片复位函数
- void phy_reset(void)
- {
- /* phy复位相关代码 */
- }
10.5 网络功能测试
11. SDRAM设备
11.1 打开SDRAM相关的代码
11.2 修改SDRAM时序参数以及行、列、大小等参数
- /**
- * [url=home.php?mod=space&uid=247401]@brief[/url] Timing config definition
- */
- typedef struct
- {
- uint32_t latencyCAS : 2; /*!< DMC_CAS_LATENCY_T */
- uint32_t tRAS : 4; /*!< DMC_RAS_MINIMUM_T */
- uint32_t tRCD : 3; /*!< DMC_DELAY_TIME_T */
- uint32_t tRP : 3; /*!< DMC_PRECHARGE_T */
- uint32_t tWR : 2; /*!< DMC_NEXT_PRECHARGE_T */
- uint32_t tARP : 4; /*!< DMC_AUTO_REFRESH_T */
- uint32_t tCMD : 4; /*!< DMC_ATA_CMD_T */
- uint32_t tXSR : 9; /*!< auto-refresh commands, can be 0x000 to 0x1FF */
- uint16_t tRFP : 16; /*!< Refresh period, can be 0x0000 to 0xFFFF */
- } DMC_TimingConfig_T;
- /**
- * [url=home.php?mod=space&uid=247401]@brief[/url] Config struct definition
- */
- typedef struct
- {
- DMC_BANK_WIDTH_T bankWidth; /*!< Number of bank bits */
- DMC_ROW_WIDTH_T rowWidth; /*!< Number of row address bits */
- DMC_COL_WIDTH_T colWidth; /*!< Number of col address bits */
- DMC_CLK_PHASE_T clkPhase; /*!< Clock phase */
- DMC_TimingConfig_T timing; /*!< Timing */
- } DMC_Config_T;
11.3 SDRAM测试
12. 总结
-
首先使能某个外设驱动设备
-
在board.h文件中定义该外设驱动相关的宏
-
在apm32_msp.c文件中添加对应外设驱动的引脚初始化代码(当然有些简单的外设,已经把引脚的初始化代码写到了外设驱动中,不需要我们再编写了,我们可以查看对应外设驱动代码是否有把引脚的初始化代码写进去了)
-
根据RTT的官方的文档介绍,添加外设驱动的使用代码。
- 本文系21ic原创,未经许可禁止转载!
网友评论
- 联系人:巧克力娃娃
- 邮箱:board@21ic.com
- 我要投稿
-
欢迎入驻,开放投稿
-
人均百万?英伟达中国员工收入曝光! 2024-08-29
-
《黑神话:悟空》玩家硬盘升级攻略:提升游戏体验,畅享3A大作 2024-08-29
-
数睿数据参加《系统与软件工程 低代码开发平台通用技术要求》国家标准编制 2024-08-29
- NRF52810蓝牙数字耳机找人定制
预算:¥30005天前
- 125KW模块式PCS软硬件外包开发
预算:¥1100000015小时前
- 12V汽车启动电源项目BMS设计
预算:¥50000023小时前
- 数据可视化软件 开发
预算:¥5000023小时前
- PLC项目调试修改
预算:¥100001天前
- 起动电机控制器开发
预算:¥1100001天前