Estoy usando el MCU STM32F103ZET6 y tengo un problema extraño en el que si programo y depuro o programo y restablezco mi MCU, el USART3 utilizado para comunicarse con un dispositivo esclavo no funciona. En la depuración, no hay datos USART que ingresen a la memoria desde el DMA, y tengo en un osciloscopio que el dispositivo esclavo envía datos constantemente. He comprobado:
Revisé el manual de referencia y la hoja de datos del dispositivo, pero tengo problemas para depurar/verificar la configuración en el código para ver la diferencia entre la ejecución de depuración/restablecimiento.
// Local Variables
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStructure;
// Code
// Configure UART
RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART3 | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); // USART3 Periph clock enable
// Configure Pins
GPIO_InitStructure.GPIO_Pin = UART3_RX_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(UART3_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = UART3_TX_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(UART3_PORT, &GPIO_InitStructure);
#if(UART3_TX_FLOW_CTS_EN == 1)
// Enable USART3 CTS pin
GPIO_InitStructure.GPIO_Pin = UART3_CTS_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(UART3_PORT, &GPIO_InitStructure);
#endif
#if(UART3_RX_FLOW_RTS_EN == 1)
// Enable USART3 RTS pin
GPIO_InitStructure.GPIO_Pin = UART3_RTS_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(UART3_PORT, &GPIO_InitStructure);
mCSP_USART3_RTS_PIN_GO;
// initialise the RTS pin as go
#endif
st_uart3_tx_glb.timeout_timer_u16 = UART3_TX_TIMEOUT;
while( (uart3_tx_flg == 0) &&
#if(UART3_TX_FLOW_CTS_EN == 1)
(mCSP_USART3_CTS_READ == 0) &&
#endif
(st_uart3_tx_glb.timeout_timer_u16 > 0) );
//Set USART3 Clock
USART_ClockStructInit(&USART_ClockInitStructure);
USART_ClockInit(USART3, &USART_ClockInitStructure);
USART_InitStructure.USART_BaudRate = baud_rate_u32;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
#if(UART3_TX_FLOW_CTS_EN == 1)
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_CTS; // Enable USART3 CTS pin
#else
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
#endif
USART_InitStructure.USART_Mode = USART_Mode_Rx |
USART_Mode_Tx;
USART_Init(USART3, &USART_InitStructure);
// Enable interrupts
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);
// Enable modules
USART_Cmd(USART3, ENABLE);
USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE);
// Enable the UART3 Interupt
// NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=USART3_IRQ_PREM_PRI;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = USART3_IRQ_SUB_PRI;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
// Configure DMA
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // DMA1 Periph clock enable
st_uart3_tx_glb.cnt_u8 = st_uart3_tx_glb.wr_index_u8;
DMA_DeInit(DMA1_Channel2);
DMA_StructInit(&DMA_UART3_InitStructure);
DMA_UART3_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART3->DR;
DMA_UART3_InitStructure.DMA_MemoryBaseAddr = (uint32_t)uart3_rx_buffer_a_u8_glb;
DMA_UART3_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_UART3_InitStructure.DMA_BufferSize = st_uart3_tx_glb.cnt_u8;
DMA_UART3_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_UART3_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_UART3_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_UART3_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_UART3_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_UART3_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_UART3_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel2, &DMA_UART3_InitStructure);
// Enable the DMA complete Interupt
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
NVIC_Init(&NVIC_InitStructure);
DMA_Cmd(DMA1_Channel2, ENABLE);
Las estructuras locales deben inicializarse; de lo contrario, algunos campos pueden obtener valores impredecibles:
GPIO_InitTypeDef GPIO_InitStructure={};
NVIC_InitTypeDef NVIC_InitStructure={};
USART_InitTypeDef USART_InitStructure={};
USART_ClockInitTypeDef USART_ClockInitStructure={};
mCSP_USART3_RTS_PIN_GO;
¿Qué hace esta declaración? ¿Es una macro o qué?
Estas banderas deben declararse volatile
, de lo contrario, puede obtener un comportamiento diferente en diferentes configuraciones de optimización:
while( (uart3_tx_flg == 0) &&
#if(UART3_TX_FLOW_CTS_EN == 1)
(mCSP_USART3_CTS_READ == 0) &&
#endif
(st_uart3_tx_glb.timeout_timer_u16 > 0) );
Fue que USART3 está en APB1 y no en el reloj APB2 y, por lo tanto, no se estaba habilitando, pero en el cargador de arranque se estaba habilitando el reloj APB1 USART3.
Jeroen3
ConfundidoQueso