[APM32F407]RTT-Studio环境下的APM32外设驱动使用指南(2)

6. PWM设备
6.1 使能PWM外设驱动

RT-Thread Setting 配置文件中使能PWM外设驱动。

6.2 在board.h文件中定义PWM外设相关的宏

这里,我打算使用定时器3的通道1进行PWM输出,所有定义PWM3这个宏。

6.3 在apm32_msp.c文件中添加定时器通道初始化代码

由于人家驱动程序并不清楚你的硬件使用的是哪个定时器哪个通道,所以把这部分的初始化程序剥离出来留给用户去写了(因为ADC外设驱动比较简单,所以ADC的引脚的初始化写进了驱动程序中)。

我使用的是PC6引脚输出PWM,就是定时器3的通道1。关于该通道初始化代码,刚好官方提供的初始化代码就有这个,所以不用重新写了。但是如果你用的不是这个定时器通道,就必须添加该部分初始化代码。

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设备使用示例,我们可以参考RTT的官方文档。

下面的代码是从RTT文档中复制过来的,PWM输出的引脚与LED相连,可以观察到 LED 灯不停的由暗变到亮,然后又从亮变到暗。

/*
 * 程序清单:这是一个 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);

我们把该代码,复制到main.c文件中,然后编译下载。然后再串口终端输入 pwm_led_sample 这个命令,就可观察到板子的LED灯不停的由暗到亮了(要确保PWM输出的引脚与LED的引脚相连了)。

7. SPI设备
7.1 使能SPI外设驱动和串行Flash驱动程序

我的硬件板子,SPI外设是连接了 SPI Flash 芯片的,所以我们在开启使能SPI外设驱动时,把SPI Flash驱动程序也一起打开,如下:

7.2 在board.h文件中定义SPI相关的宏

我所使用到的是SPI1,所以开启SPI1的宏定义。

7.3 在apm32_msp.c中编写SPI外设引脚的初始化代码

对于SPI驱动程序,需要用户自己去编写对于的SPI外设引脚初始化代码。我的板子所使用到的是SPI1PB3/4/5引脚,所以相关初始化代码如下:

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
}

如果你使用的是其他SPI引脚,编写对于的SPI引脚初始化代码即可。

7.4 挂载SPI设备

SPI 驱动会注册 SPI 总线,SPI 设备需要挂载到已经注册好的 SPI 总线上。

SPI驱动程序已经提供好了  rt_spi_bus_attach_device 这个函数进行SPI设备的挂载了。我们调用该函数就可以SPI Flash设备挂载到某个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);

把上述代码复制到 main.c 文件中(我这里只是为了测试验证,为了方便并没有新建一个文件,而是直接复制到main.c文件),然后编译下载程序,查看串口终端输出信息如下:

可以看到,已经发现了一个华邦的SPI Flash芯片,而且容量大小是 16M byte

8. CAN设备

8.1 使能CAN外设驱动

打开 RT-Thread Settings ,使能CAN设备驱动程序。

8.2 在board.h定义与CAN外设相关的宏

RTT-Studio 自动生成的 board.h 文件,还没有CAN相关的宏定义,那么我们就自己定义CAN外设驱动所需要的宏定义即可。定义如下的宏:

#define BSP_USING_CAN1
#define BSP_USING_CAN2

用到哪个CAN,就定义哪个就行。

8.3 在apm32_msp.c文件中编写CAN引脚初始化代码

同样的,自己板子用到的是哪路CAN,哪个引脚,还需要在apm32_msp.c文件中编写引脚相关的初始化代码。下面的CAN引脚初始化代码,是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设备使用示例

CAN设备驱动的使用示例,可以参考RTT官方文档 https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/device/can/can ,文档有详细的介绍。下面我就简单介绍下使用步骤:

  • 首先把文档中的示例代码复制到main.c文件,然后编译下载。
  • 使用CAN分析仪连接到你板子的CANH和CANL(我所使用的是创芯科技的CAN分析仪)。
  • 打开创芯科技的CAN分析仪上位机软件,然后按照1M的波特率启动设备(因为CAN驱动程序默认的波特率是1M,如果你修改了CAN驱动程序中的波特率,那么CAN接收数据的上位机设置的波特率要与之对应)。
  • 在串口终端运行 can_sample 这个命令。
  • 然后查看 CAN 上位机工具是否接收到了开发板发送的CAN数据。
  • 也可以提供CAN上位机发送数据到开发板,然后板子会把接收到的数据打印出来。

详细的使用示例可以看RTT的文档,我这里不再重复介绍了。

9. SDIO设备
9.1 使能SDIO外设驱动以及FatFs

1、使能SDIO设备驱动程序,有些要填写的参数,默认值就行。

2、使能虚拟文件系统和FatFs

9.2 在board.h文件中定义SDIO外设相关的宏

9.3 在apm32_msp.c文件中编写SDIO引脚初始化代码

对于SDIO外设,使能的引脚基本都是固定的,所以 apm32_msp.c 给出的代码就可以直接使用,不用修改引脚初始化相关的代码。

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文件系统

经过上面的步骤之后,SDIO其实已经正常工作起来了的。然后,我们把下面的代码复制到 main.c 文件中。

#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);

最后编译下载程序,可以看到串口终端输出如下信息:

说明SD卡已经挂载到了根目录 "/" 了。这时,我们可以使用 ls/cat/cd 等等基本的文件系统操作命令。

10. ETH设备
10.1 使能LwIP堆栈

RT-Thread Settings ,使能网络接口设备和LwIP堆栈。由于我的开发板没有插路由器,而是直接插到电脑的网口了,所以把DHCP功能给关掉,使用静态IP地址。默认静态IP: 192.168.1.30 。可以自己更改。

10.2 在board.h中定义以太网相关的宏

我们在board.h中开启以太网设备的宏定义,以及使能相关的PHY芯片宏定义。

10.3 在apm32_msp.c文件中添加ETH外设初始化代码

使能了LwIP之后,我们还需要添加以太网外设引脚初始化相关的代码。我们需要根据原理图,确认MCU和物理层芯片是通过 RMII 还是 MII 接口连接的,然后在apm32_msp.c 文件中添加对应接口引脚的初始化代码。我使用的是 RMII 接口,对应引脚初始化代码如下:

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 芯片复位函数

我们需要通过原理图确认,自己硬件板子上的 phy 芯片的复位引脚具体是连接到了那个 GPIO 口,当然也有可能是 phy 芯片的复位引脚没有连接到任何 GPIO 口,而是连接到了硬件的复位电路上,这个时候我们就不需要编写该函数的任何内容,但为了避免编译报错,还是要编写一个  void phy_reset(void)

我的硬件板子 phy 复位引脚就没有连接到任何的 GPIO 口,所以只需要编写下面的空函数即可。

void phy_reset(void)
{
        /* phy复位相关代码 */
}

10.5 网络功能测试

做完上面的步骤之后,我们就可以编译下载程序了。程序启动后可以在串口终端看到如下打印信息,输入 ifconfig 命令可以打印网络连接状态和 IP 地址。

保证我们的电脑和开发板的IP地址在同一网段,然后我们在电脑的命令行终端输入ping命令,可以看到电脑可以ping通开发板。

然后我们在串口终端输入ping命令,去ping电脑的IP地址,如下:

也可以正常ping通电脑的IP,说明网络功能已经正常运行起来了。

11. SDRAM设备
11.1 打开SDRAM相关的代码

对于SDRAM的使用,并不用使能什么设备驱动(RTT也没有SDRAM设备框架),我们只需要在 board.h 文件中定义 BSP_USING_SDRAM 这个宏,把SDRAM相关的代码开启即可。

11.2 修改SDRAM时序参数以及行、列、大小等参数

drv_sdram.c 文件中,已经提供了 SDRAM 的时序及 SDRAM 行列宽度,SDRAM大小等参数的初始化了。但是提供的那些参数可能不一定适用于你使用的 SDRAM芯片,我们需要根据SDRAM的芯片手册参数进行更改代码。

APM32 的固件库函数中,DMC_TimingConfig_T 这个结构体就是时序结构体,需要根据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;

然后还有一个初始化结构体,主要适合SDRAM行列宽度,bank宽度有关的,我们也需要根据SDRAM芯片的特性对其进行赋值,该结构体定义如下:

/**
 * [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;

我们要在 drv_sdram.c drv_sdram.h 文件中,根据自己所使用的 SDRAM 芯片的特性,对时序结构体和初始化结构体进行赋值,修改对应的代码,下面是 drv_sdram.c 文件中的 SDRAM_Init 函数部分代码截图,我们主要就是要修改下这部分代码。

11.3 SDRAM测试

我们修改完 SDRAM 的时序结构体和初始化结构体的参数之后,编译下载到板子运行,可以看到下面的提示信息:

然后我们可以在串口终端中输入SDRAM的读写测试命令, sdram_test,可以看到测试结果如下:

可以看到SDRAM读写测试成功,说明SDRAM就可以正常使用起来了。

12. 总结

以上就是对部分外设驱动使用介绍了,基本上我们要使用 APM32 的某一个外设驱动,大致的步骤都是差不多的。

  • 首先使能某个外设驱动设备
  • 在board.h文件中定义该外设驱动相关的宏
  • 在apm32_msp.c文件中添加对应外设驱动的引脚初始化代码(当然有些简单的外设,已经把引脚的初始化代码写到了外设驱动中,不需要我们再编写了,我们可以查看对应外设驱动代码是否有把引脚的初始化代码写进去了)
  • 根据RTT的官方的文档介绍,添加外设驱动的使用代码。

上面并没有把所有的外设驱动使用都介绍完,还有一些没有介绍的外设驱动使用起来也比较简单,这里就不一一介绍了。大家只要对照着上面的使用步骤,然后结合RTT的官方文档介绍,基本都可以使用起来。
---------------------
作者:luobeihai
链接:https://bbs.21ic.com/icview-3297252-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值