USART + DMA发送错误的字节数(STM32F407VGT6,RS485)

时间:2019-04-02 13:05:15

标签: stm32 uart dma ll

我正在尝试将项目从HAL迁移到LL。我使用USART1 + DMA2(RS485)。接收还可以,但是传输不可以。

例如传输缓冲区以{1、2、3、4}开头。

  • 当我将DMA数据长度设置为1时,没有任何内容发送
  • 当我将数据长度设置为2时,将发送{0xFF}
  • 当我将数据长度设置为3时,将发送{0x01,0xFF}
  • 当我将数据长度设置为4时,将发送{0x01、0x02、0xFF}

“已发送”表示我在PC的端口监视器中看到的内容。因此数据没有损坏,只是不完整。

我尝试过启用/禁用中断,清除标志。另外,我试图在LL中获得与HAL中相同的DMA和UART寄存器状态。到目前为止没有成功。

...
typedef uint8_t   uiRX_t;
typedef uint8_t   uiTX_t;

#define TX_BUFF_LEN   320
#define RX_BUFF_LEN   1

typedef struct {
  uint16_t  tx_len;
  uiTX_t    tx_buff[ TX_BUFF_LEN ];
  uiRX_t    rx_buff[ RX_BUFF_LEN ];
} DataStorage;
...
volatile  DataStorage  data = { 0 };

...

int main()
{
  ...
  while ( 1 ) {
    while ( LL_DMA_IsEnabledStream( USART_DMA, USART_DMA_STREAM_TX ) ) { }

    LL_DMA_SetDataLength( USART_DMA, USART_DMA_STREAM_TX, data.tx_len );
    LL_GPIO_SetOutputPin( USART_PORT, USART_PIN_DE );
    LL_DMA_EnableStream( USART_DMA, USART_DMA_STREAM_TX );

    LL_mDelay( SYSTICKS_FREQ );
  }
}

...

void  init_sys( void ) {
  ...
  LL_APB2_GRP1_EnableClock( LL_APB2_GRP1_PERIPH_SYSCFG );
  LL_APB1_GRP1_EnableClock( LL_APB1_GRP1_PERIPH_PWR );
  LL_PWR_SetRegulVoltageScaling( LL_PWR_REGU_VOLTAGE_SCALE1 );

  NVIC_SetPriorityGrouping( NVIC_PRIORITYGROUP_3 );

  LL_UTILS_PLLInitTypeDef   pll = {
                              .PLLM = LL_RCC_PLLM_DIV_16,
                              .PLLN = 336,
                              .PLLP = LL_RCC_PLLP_DIV_2
                            };

  LL_UTILS_ClkInitTypeDef   clk = {
                              .AHBCLKDivider  = LL_RCC_SYSCLK_DIV_1,
                              .APB1CLKDivider = LL_RCC_APB1_DIV_4,
                              .APB2CLKDivider = LL_RCC_APB2_DIV_2
                            };

  if( SUCCESS != LL_PLL_ConfigSystemClock_HSI( &pll, &clk ) ) {
    Error_Handler();
  }

  LL_SYSTICK_SetClkSource( LL_SYSTICK_CLKSOURCE_HCLK );
  LL_InitTick( SystemCoreClock, SYSTICKS_FREQ );
  LL_SYSTICK_EnableIT();
}

...

void init_nvic( const IRQn_Type irq, const uint32_t priority0, const uint32_t priority1 ) {
  NVIC_SetPriority( irq, NVIC_EncodePriority( NVIC_GetPriorityGrouping(), priority0, priority1 ) );
  NVIC_EnableIRQ( irq );
}

...

void  init_dma() {
  LL_AHB1_GRP1_EnableClock( USART_DMA_PERIPH );

  init_nvic( USART_DMA_TX_IRQn, 1, 0 );

  LL_DMA_SetChannelSelection( USART_DMA, USART_DMA_STREAM_TX, USART_DMA_CHANNEL_TX );

  LL_DMA_ConfigTransfer( USART_DMA, USART_DMA_STREAM_TX,
                        LL_DMA_DIRECTION_MEMORY_TO_PERIPH |
                        LL_DMA_MODE_NORMAL                |
                        LL_DMA_PERIPH_NOINCREMENT         |
                        LL_DMA_MEMORY_INCREMENT           |
                        LL_DMA_PDATAALIGN_BYTE            |
                        LL_DMA_MDATAALIGN_BYTE            |
                        LL_DMA_PRIORITY_HIGH );

  LL_DMA_DisableFifoMode( USART_DMA, USART_DMA_STREAM_TX );

  LL_DMA_ConfigAddresses( USART_DMA, USART_DMA_STREAM_TX,
                         ( ( uint32_t ) data.tx_buff ),
                         LL_USART_DMA_GetRegAddr( USART_N ),
                         LL_DMA_GetDataTransferDirection( USART_DMA, USART_DMA_STREAM_TX ) );

  LL_DMA_EnableIT_TC( USART_DMA, USART_DMA_STREAM_TX );
  LL_DMA_EnableIT_TE( USART_DMA, USART_DMA_STREAM_TX );
}

...

void  DMA_TransmitComplete_Callback( void )
{
  LL_GPIO_ResetOutputPin( USART_PORT, USART_PIN_DE );
  LL_DMA_DisableStream( USART_DMA, USART_DMA_STREAM_TX );
}

void  DMA_TransferError_Callback( void )
{
  LL_DMA_DisableStream( USART_DMA, USART_DMA_STREAM_TX );
}

也许最好提供完整的文件,因为它们很短,但是SO不建议这样做。可以找到完整的项目here

0 个答案:

没有答案