打印
[活动]

【APM32F411V Tiny Board测评】综合测试

[复制链接]
221|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
感谢论坛和极海提供的APM32F411-TINY开发板,通过两周的学习,对F411芯片的基础外设做了简单的测试。
1、RTOS
        本测试使用RTX操作系统,ARM针对M家族芯片做好了适配,选择对应的文件即可完成操作系统的添加。
        RTX的启动相对较为简单,代码如下:
 osKernelInitialize(); // Initialize CMSIS-RTOS
       
        thread_obj_init();
       
        thread_init();

        if (osKernelGetState() == osKernelReady)
        {
                osKernelStart(); // Start thread execution
        }
2、串口控制台
        为方便人机交互,本测试工程添加了一组控制台程序,使用方法类似SHELL,可从串口输入命令来执行内部函数。控制台是一个独立的任务,串口使用板载调试器的串口进行连接,效果如下:打开串口输入SHELL -H可查看可用命令

       
3、DMA 测试
        F411用有两组DMA模块,可以极大释放CPU占用率,提高系统运行速度。为了方便使用,本次测试封装了一组DMA接口:包含以下功能:
 /*******************************************************************************
         * [url=home.php?mod=space&uid=247401]@brief[/url]  APP DMA type
         *******************************************************************************/
        typedef struct
        {
                DMA_T *DMAx;                                                // DMA 模块
                DMA_Stream_T *stream;                            // DMA 数据流
                uint16_t ch_num;                                        // DMA 通道编号
                uint16_t trig_src;                                         // DMA 触发源
                IRQn_Type irqn;                                                // 中断号
        } app_dma_type;

#ifdef IN_DMA_MOUDLE
#define dma_stream_make(name, dmax, ch, src) \
        const app_dma_type name = {              \
                .DMAx = dmax,                        \
                .stream = dmax##_Stream##ch,       \
                .ch_num = ch,                        \
                .trig_src = src,                     \
                .irqn = dmax##_STR##ch##_IRQn}
#else
#define dma_stream_make(name, dmax, ch, src) \
        extern const app_dma_type name
#endif

        /*******************************************************************************
         * @brief  APP DMA CONFIG
         *******************************************************************************/
        dma_stream_make(DMA_U01_RX, DMA2, 2, 4);
        dma_stream_make(DMA_U01_TX, DMA2, 7, 4);

        dma_stream_make(DMA_U04_RX, DMA1, 2, 4);
        dma_stream_make(DMA_U04_TX, DMA1, 4, 4);

        dma_stream_make(DMA_U06_RX, DMA2, 1, 5);
        dma_stream_make(DMA_U06_TX, DMA2, 6, 5);
       
        dma_stream_make(DMA_ADC, DMA2, 0, 0);

        /*******************************************************************************
         * @brief  中断回调注册
         *******************************************************************************/
        typedef struct
        {
                void (*stream10)(void);
                void (*stream11)(void);
                void (*stream12)(void);
                void (*stream13)(void);
                void (*stream14)(void);
                void (*stream15)(void);
                void (*stream16)(void);
                void (*stream17)(void);
                void (*stream20)(void);
                void (*stream21)(void);
                void (*stream22)(void);
                void (*stream23)(void);
                void (*stream24)(void);
                void (*stream25)(void);
                void (*stream26)(void);
                void (*stream27)(void);
        } dma_it_type;

        extern dma_it_type dma_it;

        /*******************************************************************************
         * @brief  APP DMA API
         *******************************************************************************/
        void dma_nvic_set(const app_dma_type *dmax, uint32_t irq_en, void (*callback)(void));

        /*******************************************************************************
         * @brief  配置
         *******************************************************************************/
        typedef struct
        {
                uint8_t mem_to_periph;
                uint8_t cycle_mode;
                uint8_t mem_inc, periph_inc;
                uint16_t data_len;
                DMA_PRIORITY_T prio;
                void *mem;
                volatile void *periph;
        } dma_stream_cfg_type;

        void dma_stream_config(const app_dma_type *dmax, dma_stream_cfg_type *cfg);
        /*******************************************************************************
         * @brief  获取传输完成标志
         * \param[in] dma
         * \retval:  0-No 1-Yes
         *******************************************************************************/
        __STATIC_INLINE uint32_t dma_comp_flag_get(const app_dma_type *dmax)
        {
                int ch_num = dmax->ch_num;
                uint32_t bit_pos = ((ch_num % 4) / 2) * 16 + (ch_num % 2) * 6 + 5;

                return ((&(dmax->DMAx->LINTSTS))[ch_num / 4] >> bit_pos) & 1;
        }

        /*******************************************************************************
         * @brief  清除传输完成标志
         * \param[in] dma
         * \retval:  0-No 1-Yes
         *******************************************************************************/
        __STATIC_INLINE void dma_comp_flag_clr(const app_dma_type *dmax)
        {
                int ch_num = dmax->ch_num;
                uint32_t bit_pos = ((ch_num % 4) / 2) * 16 + (ch_num % 2) * 6 + 5;

                (&(dmax->DMAx->LIFCLR))[ch_num / 4] = 0x3DUL << bit_pos;
        }

/*******************************************************************************
* @brief  库接口映射
* \param[in] dma
* \retval:  0-No 1-Yes
*******************************************************************************/
/* 反初始化 */
#define dma_stream_deinit(dmax) DMA_Reset((dmax)->stream)

/* 判断是否已使能DMA数据流 */
#define is_dma_stream_enable(dmax) (dmax)->stream->SCFG_B.EN

/* 使能DMA数据流 */
#define dma_stream_enable(dmax) \
        dma_comp_flag_clr(dmax);    \
        DMA_Enable((dmax)->stream)

/* 禁能DMA数据流 */
#define dma_stream_disable(dmax) DMA_Disable((dmax)->stream)

/* 设置DMA数据流RAM地址 */
#define dma_stream_set_mem_addr(dmax, addr) (dmax)->stream->M0ADDR = (addr)

/* 设置DMA数据流外设地址 */
#define dma_stream_set_periph_addr(dmax, addr) (dmax)->stream->PADDR = (addr)

/* 设置DMA数据流数据长度 */
#define dma_stream_set_data_len(dmax, len) (dmax)->stream->NDATA = (len)

/* 获取DMA数据流剩余传输长度 */
#define dma_stream_get_data_len(dmax) (dmax)->stream->NDATA

/* 使能数据流传输完成中断 */
#define dma_stream_complete_isr_enable(dmax) (dmax)->stream->SCFG_B.TXCIEN = 1
封装后,DMA的使用更加方便,具体的使用参加控制台串口,该串口收发数据使用了DMA优化。

4、MODBUS测试
        本程序开通了4路MODBUS接口,分别使用UART2/3/4/6,其中U3/4做主站,U2/6做从站。
  // master config
        qc03_Init(QC_MODE_MASTER, 115200, MB_PAR_NONE);
        mb.qc03.os_event_send = mb3_os_event_send;
        qc04_Init(QC_MODE_MASTER, 19200, MB_PAR_NONE);
        mb.qc04.os_event_send = mb3_os_event_send;
       
        mcmd.id = 1;
        mcmd.wdat = &mb_input[0].uval;
        mcmd.rdat = &mb_input[0].uval;
        mcmd.wa = 0;
        mcmd.wn = 96;
        mcmd.ra = 0x1800;
        mcmd.rn = 1;
        mcmd.callback = qc_callback;
        mcmd.attr = QC_MB_ATTR_HOLD_MW;
        mqc_stc_cmd_req(&mb.qc03, 0, &mcmd);
        mqc_stc_cmd_req(&mb.qc04, 0, &mcmd);
       
        mcmd.wdat = &mb_input[0].uval;
        mcmd.wa = 96;
        mcmd.wn = 96;
        mqc_stc_cmd_req(&mb.qc03, 1, &mcmd);
        mqc_stc_cmd_req(&mb.qc04, 0, &mcmd);
       
        // slave config
        qc02_Init(QC_MODE_SLAVE, 115200, MB_PAR_NONE);
        mb.qc02.os_event_send = mb2_os_event_send;
       
        qc06_Init(QC_MODE_SLAVE, 19200, MB_PAR_NONE);
        mb.qc06.os_event_send = mb8_os_event_send;
       
        mcmd.id = 1;
        mcmd.wdat = &mb_input[0].uval;
        mcmd.rdat = &mb_input[0].uval;
        mcmd.wa = 16;
        mcmd.wn = 16;
        mcmd.ra = 0;
        mcmd.rn = 8;
        mcmd.callback = qc_callback;
        mcmd.attr = QC_MB_ATTR_HOLD_MW;
       
        mqc_stc_cmd_req(&mb.qc02, 0, &mcmd);
        mqc_stc_cmd_req(&mb.qc02, 1, &mcmd);
        mqc_stc_cmd_req(&mb.qc06, 0, &mcmd);
        mqc_stc_cmd_req(&mb.qc06, 1, &mcmd);
连接U4和U6可以进行通信,调试状态测试结果如下

       
5、SPI测试

        SPI接口外接SPI-FLASH进行测试:
        SPI 配置如下
  SPI_Config_T cfg;
        intx_alloc();

        // 开启时钟
        intx_disable();

        RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SPI1);
        RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_SPI1);
        RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_SPI1);

        intx_enable();

        // SPI 配置
        cfg.direction = SPI_DIRECTION_2LINES_FULLDUPLEX;
        cfg.baudrateDiv = SPI_BAUDRATE_DIV_16;
        cfg.mode = SPI_MODE_MASTER;
        cfg.length = SPI_DATA_LENGTH_8B;
        cfg.firstBit = SPI_FIRSTBIT_MSB;
        cfg.nss = SPI_NSS_SOFT;
        cfg.polarity = SPI_CLKPOL_LOW;
        cfg.phase = SPI_CLKPHA_1EDGE;
        cfg.crcPolynomial = 0;

        SPI_Config(NOR_SPI, &cfg);

        NOR_SPI->CTRL1_B.SPIEN = 1;

        nor_spi_cs(0);

        nor_spi_rb();

        nor_spi_cs(1);

        b_io_q_mode = 0;
在控制台输入FLASH测试命令:nor check  4 对FLASH写入4MB数据并读取验证,如下图所示:


下面附上测试代码,有兴趣的小伙伴可下载研究交流:
APM32F411-TINY.rar (8.77 MB)
       

使用特权

评论回复
沙发
星辰大海不退缩| | 2024-6-22 21:35 | 只看该作者
综合测试都有哪些具体需要注意的地方呢?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

71

主题

315

帖子

2

粉丝