Hi everyone,
Currently I'm working with the STM32L152D-EVAL board and what I want is to send a message using USART1 interface. I tried it in several ways (also with the example codes) but it seems that is no way to change the value of USART1->DR register's value and send something through serial line.
This is the code I'm using:
/** ****************************************************************************** * @file GPIO/IOToggle/main.c * @author MCD Application Team * @version V1.1.0 * @date 24-January-2012 * @brief Main program body ****************************************************************************** * @attention * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * * FOR MORE INFORMATION PLEASE READ CAREFULLY THE LICENSE AGREEMENT FILE * LOCATED IN THE ROOT DIRECTORY OF THIS FIRMWARE PACKAGE. * * <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2> ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ //#include "stm32l1xx.h" #ifdef USE_STM32L152D_EVAL #include "stm32l152d_eval.h" #elif defined USE_STM32L152_EVAL #include "stm32l152_eval.h" #endif /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ void USART_initialize(); /** * @brief Main program * @param None * @retval None */ int main(void) { /*!< At this stage the microcontroller clock setting is already configured, this is done through SystemInit() function which is called from startup file (startup_stm32l1xx_xx.s) before to branch to application main. To reconfigure the default setting of SystemInit() function, refer to system_stm32l1xx.c file */ USART_initialize(); while (1) { while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); //wait until buffer is empty (TXE=0) USART_SendData(USART1, 'O'); while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); //wait until buffer is empty (TXE=0) USART_SendData(USART1, 'K'); } } void USART_initialize(){ GPIO_InitTypeDef GPIO_Initconfig_uartport; USART_InitTypeDef USART_Initconfig_structure; /* Clock initialization */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //USART RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); //GPIOA //PA9 (Tx), PA10 (Rx) // Connect PXx to USARTx_Tx*/ GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); // Connect PXx to USARTx_Rx*/ GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); // Configure USART Tx as alternate function GPIO_Initconfig_uartport.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; GPIO_Initconfig_uartport.GPIO_Mode = GPIO_Mode_AF; //Mux out USART1 Rx & Tx with alternate function GPIO_Initconfig_uartport.GPIO_OType = GPIO_OType_PP; GPIO_Initconfig_uartport.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Initconfig_uartport.GPIO_Speed = GPIO_Speed_40MHz; GPIO_Init(GPIOA, &GPIO_Initconfig_uartport); /* USART communication parameters configuration */ USART_Initconfig_structure.USART_BaudRate = 9600; USART_Initconfig_structure.USART_WordLength = USART_WordLength_8b; USART_Initconfig_structure.USART_StopBits = USART_StopBits_1; USART_Initconfig_structure.USART_Parity = USART_Parity_No; USART_Initconfig_structure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS; USART_Initconfig_structure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_Initconfig_structure); USART_Cmd(USART1 , ENABLE); } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t* file, uint32_t line) { /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* Infinite loop */ while (1) { } } #endif /******************* (C) COPYRIGHT 2012 STMicroelectronics *****END OF FILE****/
The HAL function provided by ST is:
/** * @brief Transmits single data through the USARTx peripheral. * @param USARTx: Select the USART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param Data: the data to transmit. * @retval None. */ void USART_SendData(USART_TypeDef* USARTx, uint16_t Data) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_DATA(Data)); /* Transmit Data */ USARTx->DR = (Data & (uint16_t)0x01FF); }
Do any of you know what am I missing/doing wrong?
Thanks in advance, Kepa
This has nothing to do with Keil or ARM - it is ST's UART hardware implementation.
Take a look at the chip's technical manual: almost certainly, you will find that DR is a write-only register - you are not going to be able to read-back what you wrote to it.
Actually, it is two registers located at the same address:
1. a write-only register, which feeds the transmitter;
2. a read-only register, which is fed by the receiver.
www.st.com/.../jcr:content/translations/en.CD00240193.pdf
See 27.6.2 on page 739.
The USART->DR is a memory mapped I/O register. It references 2 different registers within the USART.
When you write to the DR register, it references the USART TX portion of the USART. when you read the DR register, it references the USART RX portion of the USART.
When you write the USART->DR it does not change what you read from USART->DR because they reference 2 different registers within the USART Hardware.
That being said, I am not sure how you are determining that the USART->DR register is not being changed when you write to it as there is just no way to read the register back to verify that it has changed.
The initialization you show looks pretty much correct EXCEPT you are saying to use CTS/RTS but you have not initialized the CTS/RTS pins. You probably want to remove using the CTS/RTS from both sides until you understand this more and see data being transmitted and received.
Whoops. Duplicate answer save the possible configuration issue. I appreciate your succinct and concise answer (Andrew Neil).
In a more general sense don't put the debugger's peripheral view over the USART, it will do annoying things like clear the RXNE bit of SR when DR is read.
For SDIO and USB peripherals with large FIFOs this can also cause significant issues.
Thanks for the answers guys. So that's why, while debugging, I can't see the value of DR changing when it is transmitted a message... However, there's something wrong since I can't see any programmed message in the TeraTerm. I'm pretty sure that the code is correct, so there might be a HW error or a serial port driver error. I still haven't identified the problem, I'm checking it. If I find what is the error I'll post here.
Thanks for the help.