- /*******************************************************************************
- * [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, 下载次数: 8)