华大芯片HC32F4A0实现RS485通讯DMA收发

1.串口初始化

    stc_irq_signin_config_t stcIrqSigninCfg;
    const stc_usart_uart_init_t stcUartInit = {
        .u32Baudrate = USART_BAUDRATE,
        .u32BitDirection = USART_LSB,
        .u32StopBit = USART_STOPBIT_1BIT,
        .u32Parity = USART_PARITY_NONE,
        .u32DataWidth = USART_DATA_LENGTH_8BIT,
        .u32ClkMode = USART_INTERNCLK_OUTPUT,
        .u32PclkDiv = USART_PCLK_DIV64,
        .u32OversamplingBits = USART_OVERSAMPLING_8BIT,
        .u32NoiseFilterState = USART_NOISE_FILTER_DISABLE,
        .u32SbDetectPolarity = USART_SB_DETECT_FALLING,
    };

    /* Configure USART RX/TX pin. */
    GPIO_SetFunc(USART_RX_PORT, USART_RX_PIN, USART_RX_GPIO_FUNC, PIN_SUBFUNC_DISABLE);
    GPIO_SetFunc(USART_TX_PORT, USART_TX_PIN, USART_TX_GPIO_FUNC, PIN_SUBFUNC_DISABLE);

2.串口接收DMA初始化

#define DMA_RX_UNIT                        (M4_DMA1)
#define DMA_RX_CH                          (DMA_CH0)
#define DMA_RX_BTC_INT                     (DMA_BTC_INT_CH0)
#define DMA_RX_BTC_INT_SRC                 (INT_DMA1_BTC0)
#define DMA_RX_BTC_INT_IRQn                (Int000_IRQn)
#define DMA_RX_FUNCTION_CLK_GATE           (PWC_FCG0_DMA1)
#define DMA_RX_TRIGGER_SOURCE              (EVT_USART6_RI)


/**
 * @brief  Initialize DMA.
 * @param  None
 * @retval en_result_t
 */
static en_result_t DMA_Rx_Config(void)
{
    en_result_t enRet;
    stc_dma_init_t stcDmaInit;
    stc_irq_signin_config_t stcIrqSignConfig;

    /* DMA&AOS FCG enable */
    PWC_FCG0_Unlock();
    PWC_Fcg0PeriphClockCmd((DMA_RX_FUNCTION_CLK_GATE | PWC_FCG0_AOS), Enable);
    PWC_FCG0_Lock();

    (void)DMA_StructInit(&stcDmaInit);
    stcDmaInit.u32IntEn = DMA_INT_DISABLE;						//中断												
    stcDmaInit.u32BlockSize = 1UL;								//1block
    stcDmaInit.u32TransCnt = RS485_RX_BUFF_LEN;					//传输长度
    stcDmaInit.u32DataWidth = DMA_DATAWIDTH_8BIT;				//8bit
    stcDmaInit.u32DestAddr = (uint32_t)(rs485_struct.rx_buff);	//目的地址
    stcDmaInit.u32SrcAddr = ((uint32_t)(&USART_UNIT->DR) + 2UL);//源地址 串口DR寄存器
    stcDmaInit.u32SrcInc = DMA_SRC_ADDR_FIX;					//源地址   固定地址
    stcDmaInit.u32DestInc = DMA_DEST_ADDR_INC;					//目的地址 地址自增
    enRet = DMA_Init(DMA_RX_UNIT, DMA_RX_CH, &stcDmaInit);
    if (Ok == enRet)
    {
        /* DMA module enable */
        DMA_Cmd(DMA_RX_UNIT, Enable);

        /* DMA channel enable */
        DMA_ChannelCmd(DMA_RX_UNIT, DMA_RX_CH, Enable);

        /* Set DMA trigger source */
        DMA_SetTriggerSrc(DMA_RX_UNIT, DMA_RX_CH, DMA_RX_TRIGGER_SOURCE);
    }
    return enRet;
}

3.串口接收DMA初始化

#define DMA_TX_UNIT                        (M4_DMA1)
#define DMA_TX_CH                          (DMA_CH1)
#define DMA_TX_BTC_INT                     (DMA_TC_INT_CH1)
#define DMA_TX_BTC_INT_SRC                 (INT_DMA1_TC1)
#define DMA_TX_BTC_INT_IRQn                (Int004_IRQn)
#define DMA_TX_FUNCTION_CLK_GATE           (PWC_FCG0_DMA1)
#define DMA_TX_TRIGGER_SOURCE              (EVT_USART6_TI)


static en_result_t DMA_Tx_Config(void)
{
    en_result_t enRet;
    stc_dma_init_t stcDmaInit;
    stc_irq_signin_config_t stcIrqSignConfig;

    /* DMA&AOS FCG enable */
    PWC_FCG0_Unlock();
    PWC_Fcg0PeriphClockCmd((DMA_TX_FUNCTION_CLK_GATE | PWC_FCG0_AOS), Enable);
    PWC_FCG0_Lock();

    (void)DMA_StructInit(&stcDmaInit);
    stcDmaInit.u32IntEn = DMA_INT_ENABLE; 		//DMA_INT_ENABLE;中断使能
    stcDmaInit.u32BlockSize = 1UL;				//块大小
    stcDmaInit.u32TransCnt = 128;				//传输128次
    stcDmaInit.u32DataWidth = DMA_DATAWIDTH_8BIT;//数据宽度8bit
    stcDmaInit.u32DestAddr = ((uint32_t)(&USART_UNIT->DR)); //目的地址TX: (&USART_UNIT->DR)
    stcDmaInit.u32SrcAddr = 0;					//源地址 空     RX: (&USART_UNIT->DR +2U) 
    stcDmaInit.u32SrcInc = DMA_SRC_ADDR_INC;	//源地址依次递增
    stcDmaInit.u32DestInc = DMA_DEST_ADDR_FIX; 	//目的地址固定	DMA_DEST_ADDR_FIX;
    enRet = DMA_Init(DMA_TX_UNIT, DMA_TX_CH, &stcDmaInit);	//初始化dmi
    if (Ok == enRet)
    {
		DMA_ClearTransIntStatus(DMA_TX_UNIT, DMA_TX_CH);

        /* Register interrupt */
		 stcIrqSignConfig.enIntSrc = DMA_TX_BTC_INT_SRC;
		 stcIrqSignConfig.enIRQn  = DMA_TX_BTC_INT_IRQn;
		 stcIrqSignConfig.pfnCallback= &dma_tx_tc_irqcallback;
		 (void)INTC_IrqSignIn(&stcIrqSignConfig);
		 NVIC_ClearPendingIRQ(stcIrqSignConfig.enIRQn);
		 NVIC_SetPriority(stcIrqSignConfig.enIRQn,DDL_IRQ_PRIORITY_DEFAULT);
		 NVIC_EnableIRQ(stcIrqSignConfig.enIRQn);

        /* DMA module enable */
        DMA_Cmd(DMA_TX_UNIT, Enable);

        /* DMA channel interrupt enable */
        DMA_TransIntCmd(DMA_TX_UNIT, DMA_TX_BTC_INT, Enable);	

        /* DMA channel enable */
        DMA_ChannelCmd(DMA_TX_UNIT, DMA_TX_CH, Enable);

        /* Set DMA trigger source */
        DMA_SetTriggerSrc(DMA_TX_UNIT, DMA_TX_CH, DMA_TX_TRIGGER_SOURCE);
    }

	DMA_SetSrcAddr(DMA_TX_UNIT, DMA_TX_CH, (uint32_t)"pbuf");

    return enRet;
}
//DMA发送完成中断
static void dma_tx_tc_irqcallback(void)
{
	DMA_ClearTransIntStatus(DMA_TX_UNIT, DMA_TX_BTC_INT);
	DDL_DelayUS(210);  //等待数据发送完成
    USART_FuncCmd(USART_UNIT, USART_TX, Disable);
	set_rx485_ctrl_pin(0);
}

4.定时器初始化

/* Timer0 unit & channel definition */
#define TMR0_UNIT                       (M4_TMR0_2)
#define TMR0_CH                         (TMR0_CH_A)
#define TMR0_FUNCTION_CLK_GATE          (PWC_FCG2_TMR0_2)

/**
 * @brief  Configure TMR0.
 * @param  None
 * @retval None
 */
static void TMR0_Config(void)
{
    uint32_t u32CmpVal;
    stc_tmr0_init_t stcTmr0Init;

    PWC_Fcg2PeriphClockCmd(TMR0_FUNCTION_CLK_GATE, Enable);

    /* Clear CNTAR register for channel A */
    TMR0_SetCntVal(TMR0_UNIT, TMR0_CH, 0U);

    /* TIMER0 basetimer function initialize */
    (void)TMR0_StructInit(&stcTmr0Init);
    stcTmr0Init.u32ClockDivision = TMR0_CLK_DIV8;
    stcTmr0Init.u32ClockSource = TMR0_CLK_SRC_XTAL32;
    stcTmr0Init.u32HwTrigFunc = (TMR0_BT_HWTRG_FUNC_START | TMR0_BT_HWTRG_FUNC_CLEAR);
    if (TMR0_CLK_DIV1 == stcTmr0Init.u32ClockDivision)
    {
        u32CmpVal = (USART_BAUDRATE - 4UL);
    }
    else if (TMR0_CLK_DIV2 == stcTmr0Init.u32ClockDivision)
    {
        u32CmpVal = (USART_BAUDRATE/2UL - 2UL);
    }
    else
    {
        u32CmpVal = (USART_BAUDRATE / (1UL << (stcTmr0Init.u32ClockDivision >> TMR0_BCONR_CKDIVA_POS)) - 1UL);
    }
    DDL_ASSERT(u32CmpVal <= 0xFFFFUL);
    stcTmr0Init.u16CmpValue =  (uint16_t)(u32CmpVal);
    (void)TMR0_Init(TMR0_UNIT, TMR0_CH, &stcTmr0Init);

    /* Clear compare flag */
    TMR0_ClearStatus(TMR0_UNIT, TMR0_CH);
}

5.串口中断使能

RS485通讯串口只需要使能接收超时中断即可
华大芯片HC32F4A0实现RS485通讯DMA收发_第1张图片
中断初始化

    /* Register RX timeout IRQ handler && configure NVIC. */
    stcIrqSigninCfg.enIRQn = USART_RXTO_INT_IRQn;
    stcIrqSigninCfg.enIntSrc = USART_RXTO_INT_SRC;
    stcIrqSigninCfg.pfnCallback = &USART_RxTimeout_IrqCallback;
    (void)INTC_IrqSignIn(&stcIrqSigninCfg);
    NVIC_ClearPendingIRQ(stcIrqSigninCfg.enIRQn);
    NVIC_SetPriority(stcIrqSigninCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
    NVIC_EnableIRQ(stcIrqSigninCfg.enIRQn);

    /* Enable TX && RX && RX interrupt function */
    USART_FuncCmd(USART_UNIT, (USART_RX | USART_INT_RX | USART_TX | \
                               USART_RTO | USART_INT_RTO), Enable);

6.超时接收中断


/**
 * @brief  USART RX timeout IRQ callback.
 * @param  None
 * @retval None
 */
static void USART_RxTimeout_IrqCallback(void)
{
    TMR0_Cmd(TMR0_UNIT, TMR0_CH, Disable);
    USART_ClearStatus(USART_UNIT, USART_CLEAR_FLAG_RTOF);
	DMA_ChannelCmd(DMA_RX_UNIT, DMA_RX_CH, Disable);
//    memcpy(&data_arry[0], &uart_buf[0], sizeof(data_arry));
    rs485_struct.rx_len = RS485_RX_BUFF_LEN - DMA_GetTransCnt(DMA_RX_UNIT, DMA_RX_CH);
	memset(rs485_struct.rx_buff, 0, sizeof(rs485_struct.rx_buff));
	//printf("\r\nble recv %d %s\r\n",BleDMARecieve.len,BleDMARecieve.data);
    DMA_SetDestAddr(DMA_RX_UNIT, DMA_RX_CH, (uint32_t)(&rs485_struct.rx_buff[0]));
    DMA_SetBlockSize(DMA_RX_UNIT, DMA_RX_CH, 1);
    DMA_SetTransCnt(DMA_RX_UNIT, DMA_RX_CH, RS485_RX_BUFF_LEN);
    DMA_ChannelCmd(DMA_RX_UNIT, DMA_RX_CH, Enable);  
}

7.发送函数

//DMA发送完成中断
static void dma_tx_tc_irqcallback(void)
{
	DMA_ClearTransIntStatus(DMA_TX_UNIT, DMA_TX_BTC_INT);
	DDL_DelayUS(210);  //等待数据发送完成
    USART_FuncCmd(USART_UNIT, USART_TX, Disable);
	set_rx485_ctrl_pin(0);
}
void rx485_send(uint8_t *pData, uint16_t Cnt)
{
	set_rx485_ctrl_pin(1);
    DMA_ChannelCmd(DMA_TX_UNIT, DMA_TX_CH, Disable);
	USART_FuncCmd(USART_UNIT, USART_TX, Disable);
	USART_FuncCmd(USART_UNIT, USART_INT_TXE, Disable);
    DMA_SetSrcAddr(DMA_TX_UNIT, DMA_TX_CH, (uint32_t)pData);
    DMA_SetBlockSize(DMA_TX_UNIT, DMA_TX_CH, 1);
    DMA_SetTransCnt(DMA_TX_UNIT, DMA_TX_CH, Cnt);
    DMA_ChannelCmd(DMA_TX_UNIT, DMA_TX_CH, Enable);  
	USART_FuncCmd(USART_UNIT, USART_TX, Enable);
	USART_FuncCmd(USART_UNIT, USART_INT_TXE, Enable);  
}

需要注意的是DMA发送完成中断只是将数据丢入缓冲区,并不是串口发送完成所以需要等待一段时间

static void dma_tx_tc_irqcallback(void)
{
	DMA_ClearTransIntStatus(DMA_TX_UNIT, DMA_TX_BTC_INT);
	DDL_DelayUS(210);  //等待数据发送完成
    USART_FuncCmd(USART_UNIT, USART_TX, Disable);
	set_rx485_ctrl_pin(0);
}

不多说直接看源码:

#include "bsp_rs485.h"
#include "hc32_ddl.h"

#define RS485_RX_BUFF_LEN (256)
typedef struct{
	uint8_t rx_buff[RS485_RX_BUFF_LEN];
	uint16_t rx_len;
}RS485_RX;
RS485_RX rs485_struct;
 /* DMA Unit/Channel/Interrupt definition */
#define DMA_RX_UNIT                        (M4_DMA1)
#define DMA_RX_CH                          (DMA_CH0)
#define DMA_RX_BTC_INT                     (DMA_BTC_INT_CH0)
#define DMA_RX_BTC_INT_SRC                 (INT_DMA1_BTC0)
#define DMA_RX_BTC_INT_IRQn                (Int000_IRQn)
#define DMA_RX_FUNCTION_CLK_GATE           (PWC_FCG0_DMA1)
#define DMA_RX_TRIGGER_SOURCE              (EVT_USART6_RI)

#define DMA_TX_UNIT                        (M4_DMA1)
#define DMA_TX_CH                          (DMA_CH1)
#define DMA_TX_BTC_INT                     (DMA_TC_INT_CH1)
#define DMA_TX_BTC_INT_SRC                 (INT_DMA1_TC1)
#define DMA_TX_BTC_INT_IRQn                (Int004_IRQn)
#define DMA_TX_FUNCTION_CLK_GATE           (PWC_FCG0_DMA1)
#define DMA_TX_TRIGGER_SOURCE              (EVT_USART6_TI)

/* Timer0 unit & channel definition */
#define TMR0_UNIT                       (M4_TMR0_2)
#define TMR0_CH                         (TMR0_CH_A)
#define TMR0_FUNCTION_CLK_GATE          (PWC_FCG2_TMR0_2)

/* UART unit definition */
#define USART_UNIT                      (M4_USART6)
#define USART_BAUDRATE                  (115200UL)
#define USART_FUNCTION_CLK_GATE         (PWC_FCG3_USART6)

/* UART unit interrupt definition */
#define USART_TC_INT_SRC             	(INT_USART6_TCI)
#define USART_TC_INT_IRQn            	(Int001_IRQn)

#define USART_RXTO_INT_SRC              (INT_USART6_RTO)
#define USART_RXTO_INT_IRQn             (Int002_IRQn)

/* UART RX/TX Port/Pin definition */
#define USART_RX_PORT                   (GPIO_PORT_H)   /* PH13: USART1_RX */
#define USART_RX_PIN                    (GPIO_PIN_06)
#define USART_RX_GPIO_FUNC              (GPIO_FUNC_37_USART6_RX)

#define USART_TX_PORT                   (GPIO_PORT_H)   /* PH15: USART1_TX */
#define USART_TX_PIN                    (GPIO_PIN_07)
#define USART_TX_GPIO_FUNC              (GPIO_FUNC_36_USART6_TX)

#define RX485_CTRL_PROT                 (GPIO_PORT_H)
#define RX485_CTRL_PIN                  (GPIO_PIN_05)

/*******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/

/*******************************************************************************
 * Local function prototypes ('static')
 ******************************************************************************/
static en_result_t DMA_Rx_Config(void);
static void TMR0_Config(void);
static void DMA_Btc_IrqCallback(void);
static void USART_RxErr_IrqCallback(void);
static void USART_RxTimeout_IrqCallback(void);
static void dma_tx_tc_irqcallback(void);
static void set_rx485_ctrl_pin(uint8_t state);
/*******************************************************************************
 * Local variable definitions ('static')
 ******************************************************************************/
static en_functional_state_t m_enLedOn = Disable;
static en_functional_state_t m_enLedCurrentStatus = Disable;

/*******************************************************************************
 * Function implementation - global ('extern') and local ('static')
 ******************************************************************************/

/**
 * @brief  Initialize DMA.
 * @param  None
 * @retval en_result_t
 */
static en_result_t DMA_Rx_Config(void)
{
    en_result_t enRet;
    stc_dma_init_t stcDmaInit;
    stc_irq_signin_config_t stcIrqSignConfig;

    /* DMA&AOS FCG enable */
    PWC_FCG0_Unlock();
    PWC_Fcg0PeriphClockCmd((DMA_RX_FUNCTION_CLK_GATE | PWC_FCG0_AOS), Enable);
    PWC_FCG0_Lock();

    (void)DMA_StructInit(&stcDmaInit);
    stcDmaInit.u32IntEn = DMA_INT_DISABLE;						//中断												
    stcDmaInit.u32BlockSize = 1UL;								//1block
    stcDmaInit.u32TransCnt = RS485_RX_BUFF_LEN;					//传输长度
    stcDmaInit.u32DataWidth = DMA_DATAWIDTH_8BIT;				//8bit
    stcDmaInit.u32DestAddr = (uint32_t)(rs485_struct.rx_buff);	//目的地址
    stcDmaInit.u32SrcAddr = ((uint32_t)(&USART_UNIT->DR) + 2UL);//源地址 串口DR寄存器
    stcDmaInit.u32SrcInc = DMA_SRC_ADDR_FIX;					//源地址   固定地址
    stcDmaInit.u32DestInc = DMA_DEST_ADDR_INC;					//目的地址 地址自增
    enRet = DMA_Init(DMA_RX_UNIT, DMA_RX_CH, &stcDmaInit);
    if (Ok == enRet)
    {
        /* DMA module enable */
        DMA_Cmd(DMA_RX_UNIT, Enable);

        /* DMA channel enable */
        DMA_ChannelCmd(DMA_RX_UNIT, DMA_RX_CH, Enable);

        /* Set DMA trigger source */
        DMA_SetTriggerSrc(DMA_RX_UNIT, DMA_RX_CH, DMA_RX_TRIGGER_SOURCE);
    }
    return enRet;
}

static en_result_t DMA_Tx_Config(void)
{
    en_result_t enRet;
    stc_dma_init_t stcDmaInit;
    stc_irq_signin_config_t stcIrqSignConfig;

    /* DMA&AOS FCG enable */
    PWC_FCG0_Unlock();
    PWC_Fcg0PeriphClockCmd((DMA_TX_FUNCTION_CLK_GATE | PWC_FCG0_AOS), Enable);
    PWC_FCG0_Lock();

    (void)DMA_StructInit(&stcDmaInit);
    stcDmaInit.u32IntEn = DMA_INT_ENABLE; 		//DMA_INT_ENABLE;中断使能
    stcDmaInit.u32BlockSize = 1UL;				//块大小
    stcDmaInit.u32TransCnt = 128;				//传输128次
    stcDmaInit.u32DataWidth = DMA_DATAWIDTH_8BIT;//数据宽度8bit
    stcDmaInit.u32DestAddr = ((uint32_t)(&USART_UNIT->DR)); //目的地址TX: (&USART_UNIT->DR)
    stcDmaInit.u32SrcAddr = 0;					//源地址 空     RX: (&USART_UNIT->DR +2U) 
    stcDmaInit.u32SrcInc = DMA_SRC_ADDR_INC;	//源地址依次递增
    stcDmaInit.u32DestInc = DMA_DEST_ADDR_FIX; 	//目的地址固定	DMA_DEST_ADDR_FIX;
    enRet = DMA_Init(DMA_TX_UNIT, DMA_TX_CH, &stcDmaInit);	//初始化dmi
    if (Ok == enRet)
    {
		DMA_ClearTransIntStatus(DMA_TX_UNIT, DMA_TX_CH);

        /* Register interrupt */
		 stcIrqSignConfig.enIntSrc = DMA_TX_BTC_INT_SRC;
		 stcIrqSignConfig.enIRQn  = DMA_TX_BTC_INT_IRQn;
		 stcIrqSignConfig.pfnCallback= &dma_tx_tc_irqcallback;
		 (void)INTC_IrqSignIn(&stcIrqSignConfig);
		 NVIC_ClearPendingIRQ(stcIrqSignConfig.enIRQn);
		 NVIC_SetPriority(stcIrqSignConfig.enIRQn,DDL_IRQ_PRIORITY_DEFAULT);
		 NVIC_EnableIRQ(stcIrqSignConfig.enIRQn);

        /* DMA module enable */
        DMA_Cmd(DMA_TX_UNIT, Enable);

        /* DMA channel interrupt enable */
        DMA_TransIntCmd(DMA_TX_UNIT, DMA_TX_BTC_INT, Enable);	

        /* DMA channel enable */
        DMA_ChannelCmd(DMA_TX_UNIT, DMA_TX_CH, Enable);

        /* Set DMA trigger source */
        DMA_SetTriggerSrc(DMA_TX_UNIT, DMA_TX_CH, DMA_TX_TRIGGER_SOURCE);
    }

	DMA_SetSrcAddr(DMA_TX_UNIT, DMA_TX_CH, (uint32_t)"pbuf");

    return enRet;
}

/**
 * @brief  Configure TMR0.
 * @param  None
 * @retval None
 */
static void TMR0_Config(void)
{
    uint32_t u32CmpVal;
    stc_tmr0_init_t stcTmr0Init;

    PWC_Fcg2PeriphClockCmd(TMR0_FUNCTION_CLK_GATE, Enable);

    /* Clear CNTAR register for channel A */
    TMR0_SetCntVal(TMR0_UNIT, TMR0_CH, 0U);

    /* TIMER0 basetimer function initialize */
    (void)TMR0_StructInit(&stcTmr0Init);
    stcTmr0Init.u32ClockDivision = TMR0_CLK_DIV8;
    stcTmr0Init.u32ClockSource = TMR0_CLK_SRC_XTAL32;
    stcTmr0Init.u32HwTrigFunc = (TMR0_BT_HWTRG_FUNC_START | TMR0_BT_HWTRG_FUNC_CLEAR);
    if (TMR0_CLK_DIV1 == stcTmr0Init.u32ClockDivision)
    {
        u32CmpVal = (USART_BAUDRATE - 4UL);
    }
    else if (TMR0_CLK_DIV2 == stcTmr0Init.u32ClockDivision)
    {
        u32CmpVal = (USART_BAUDRATE/2UL - 2UL);
    }
    else
    {
        u32CmpVal = (USART_BAUDRATE / (1UL << (stcTmr0Init.u32ClockDivision >> TMR0_BCONR_CKDIVA_POS)) - 1UL);
    }
    DDL_ASSERT(u32CmpVal <= 0xFFFFUL);
    stcTmr0Init.u16CmpValue =  (uint16_t)(u32CmpVal);
    (void)TMR0_Init(TMR0_UNIT, TMR0_CH, &stcTmr0Init);

    /* Clear compare flag */
    TMR0_ClearStatus(TMR0_UNIT, TMR0_CH);
}

/**
 * @brief  DMA block transfer complete IRQ callback function.
 * @param  None
 * @retval None
 */
static void DMA_Btc_IrqCallback(void)
{
    DMA_ClearTransIntStatus(DMA_RX_UNIT, DMA_RX_BTC_INT);
}

//DMA发送完成中断
static void dma_tx_tc_irqcallback(void)
{
	DMA_ClearTransIntStatus(DMA_TX_UNIT, DMA_TX_BTC_INT);
	DDL_DelayUS(210);  //等待数据发送完成
    USART_FuncCmd(USART_UNIT, USART_TX, Disable);
	set_rx485_ctrl_pin(0);
}

/**
 * @brief  USART RX timeout IRQ callback.
 * @param  None
 * @retval None
 */
static void USART_RxTimeout_IrqCallback(void)
{
    TMR0_Cmd(TMR0_UNIT, TMR0_CH, Disable);
    USART_ClearStatus(USART_UNIT, USART_CLEAR_FLAG_RTOF);
	DMA_ChannelCmd(DMA_RX_UNIT, DMA_RX_CH, Disable);
//    memcpy(&data_arry[0], &uart_buf[0], sizeof(data_arry));
    rs485_struct.rx_len = RS485_RX_BUFF_LEN - DMA_GetTransCnt(DMA_RX_UNIT, DMA_RX_CH);
	memset(rs485_struct.rx_buff, 0, sizeof(rs485_struct.rx_buff));
	//printf("\r\nble recv %d %s\r\n",BleDMARecieve.len,BleDMARecieve.data);
    DMA_SetDestAddr(DMA_RX_UNIT, DMA_RX_CH, (uint32_t)(&rs485_struct.rx_buff[0]));
    DMA_SetBlockSize(DMA_RX_UNIT, DMA_RX_CH, 1);
    DMA_SetTransCnt(DMA_RX_UNIT, DMA_RX_CH, RS485_RX_BUFF_LEN);
    DMA_ChannelCmd(DMA_RX_UNIT, DMA_RX_CH, Enable);  
}

static void set_rx485_ctrl_pin(uint8_t state)
{
	if(state)
	{
		 GPIO_SetPins(RX485_CTRL_PROT, RX485_CTRL_PIN);
	}
	else
	{
		 GPIO_ResetPins(RX485_CTRL_PROT, RX485_CTRL_PIN);
	}	
}

void rx485_send(uint8_t *pData, uint16_t Cnt)
{
	set_rx485_ctrl_pin(1);
    DMA_ChannelCmd(DMA_TX_UNIT, DMA_TX_CH, Disable);
	USART_FuncCmd(USART_UNIT, USART_TX, Disable);
	USART_FuncCmd(USART_UNIT, USART_INT_TXE, Disable);
    DMA_SetSrcAddr(DMA_TX_UNIT, DMA_TX_CH, (uint32_t)pData);
    DMA_SetBlockSize(DMA_TX_UNIT, DMA_TX_CH, 1);
    DMA_SetTransCnt(DMA_TX_UNIT, DMA_TX_CH, Cnt);
    DMA_ChannelCmd(DMA_TX_UNIT, DMA_TX_CH, Enable);  
	USART_FuncCmd(USART_UNIT, USART_TX, Enable);
	USART_FuncCmd(USART_UNIT, USART_INT_TXE, Enable);  
}

/**
 * @brief  Main function of UART DMA project
 * @param  None
 * @retval int32_t return value, if needed
 */
void rs485_init(void)
{
    stc_irq_signin_config_t stcIrqSigninCfg;
    const stc_usart_uart_init_t stcUartInit = {
        .u32Baudrate = USART_BAUDRATE,
        .u32BitDirection = USART_LSB,
        .u32StopBit = USART_STOPBIT_1BIT,
        .u32Parity = USART_PARITY_NONE,
        .u32DataWidth = USART_DATA_LENGTH_8BIT,
        .u32ClkMode = USART_INTERNCLK_OUTPUT,
        .u32PclkDiv = USART_PCLK_DIV64,
        .u32OversamplingBits = USART_OVERSAMPLING_8BIT,
        .u32NoiseFilterState = USART_NOISE_FILTER_DISABLE,
        .u32SbDetectPolarity = USART_SB_DETECT_FALLING,
    };

    /* Initialize DMA. */
    DMA_Rx_Config();
	DMA_Tx_Config();
    /* Initialize TMR0. */
    TMR0_Config();

    /* Configure USART RX/TX pin. */
    GPIO_SetFunc(USART_RX_PORT, USART_RX_PIN, USART_RX_GPIO_FUNC, PIN_SUBFUNC_DISABLE);
    GPIO_SetFunc(USART_TX_PORT, USART_TX_PIN, USART_TX_GPIO_FUNC, PIN_SUBFUNC_DISABLE);

    stc_gpio_init_t stcGpioInit;
    (void)GPIO_StructInit(&stcGpioInit);
    stcGpioInit.u16PinDir = PIN_DIR_OUT;
    stcGpioInit.u16PinDrv = PIN_DRV_HIGH;
    (void)GPIO_Init(RX485_CTRL_PROT, RX485_CTRL_PIN, &stcGpioInit);

    /* Enable peripheral clock */
    PWC_Fcg3PeriphClockCmd(USART_FUNCTION_CLK_GATE, Enable);

    /* Initialize UART function. */
    if (Ok != USART_UartInit(USART_UNIT, &stcUartInit))
    {

    }
	
    /* Register RX timeout IRQ handler && configure NVIC. */
    stcIrqSigninCfg.enIRQn = USART_RXTO_INT_IRQn;
    stcIrqSigninCfg.enIntSrc = USART_RXTO_INT_SRC;
    stcIrqSigninCfg.pfnCallback = &USART_RxTimeout_IrqCallback;
    (void)INTC_IrqSignIn(&stcIrqSigninCfg);
    NVIC_ClearPendingIRQ(stcIrqSigninCfg.enIRQn);
    NVIC_SetPriority(stcIrqSigninCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
    NVIC_EnableIRQ(stcIrqSigninCfg.enIRQn);

    /* Enable TX && RX && RX interrupt function */
    USART_FuncCmd(USART_UNIT, (USART_RX | USART_INT_RX | USART_TX | \
                               USART_RTO | USART_INT_RTO), Enable);
	//使能接收模式				   
	set_rx485_ctrl_pin(0);	
}

你可能感兴趣的:(华大芯片,单片机,stm32,嵌入式硬件)