Stuck with USART stm32f103rct6

0

I was try to interface USART of STMF103RCT6(specifically USART1 PA9- Tx and PA10- RX). I have done my PLL Configuration for running my system at 72MHz and having few problems.

I have connected RX/TX pin of stm32f103rct6 to USB-to-Serial TX/RX and receive a character 'A' in the terminal(Software: Tera Term) at baud rate of 115200. But its not working.

Here is my code:

#include "stm32f10x.h"

 #define HPRE_RESET_MASK        ((uint32_t)0xFFFFFF0F)
 #define PPRE2_RESET_MASK       ((uint32_t)0xFFFFC7FF)
 #define PPRE1_RESET_MASK       ((uint32_t)0xFFFFF8FF)
 #define PLLCLK_CONFIG_RESET_MASK   ((uint32_t)0xFFC0FFFF)
 #define SW_RESET_MASK          ((uint32_t)0xFFFFFFFC)


 #define LED_PORT_EN()  ( RCC->APB2ENR |= RCC_APB2ENR_IOPDEN )
 #define LED_PORT       GPIOD

 #define LED_MODE_BIT1          8
 #define LED_MODE_BIT2          9
 #define LED_CNF_BIT1           10
 #define LED_CNF_BIT2           11


 #define CNF_SET_PORTD(BIT1,BIT2)   (   LED_PORT->CRL &= ~((1<<BIT1) | (1<<BIT2)) ) //General purpose output push-pull
 #define MODE_SET_PORTD(BIT1,BIT2)  ( LED_PORT->CRL |=  (1<<BIT1) | (1<<BIT2) )  //Output mode, max speed 50 MHz.

 #define SET_GPIO_BIT_PORTD(BIT)    ( LED_PORT->BSRR =  (1 << BIT) )     //For setting the Bit  
 #define RESET_GPIO_BIT_PORTD(BIT)  ( LED_PORT->BSRR =  ( (1 << BIT) << 16 )    )   //For Resseting Bit




 void PLL_Config(void);
 void Clock_Reset(void);
 void HCLK_Config(uint32_t RCC_SYSCLK);
 void PCLK2_Config(uint32_t RCC_HCLK);
 void PCLK1_Config(uint32_t RCC_HCLK);
 void PLLCLK_Config(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul); 
 void SYSCLK_Config(uint32_t RCC_SYSCLKSource);
 void Delay(int ms);
 void Led_Init(void);
 void Blink_Led(int ms);
 void Transmit_Char(char data);


int main(void)
{

    PLL_Config();
    Led_Init();
    //RCC configure for PORTA
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
    /*for uart 1*/
    GPIOA->CRH |= GPIO_CRH_MODE9;       //Configure TX PORTA 9 push pull
    GPIOA->CRH &= ~(GPIO_CRH_CNF9);

    GPIOA->CRH |= GPIO_CRH_MODE10;      //Configure RX PORTA 10 push pull
    GPIOA->CRH &= ~(GPIO_CRH_CNF10);

    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;   //enable clock for usart
    USART1->BRR = 0x271;    //set Baud mantisa 0x27  fraction 0x1
    /*enable usart,   enable RX,TX  */
    USART1->CR1 = USART_CR1_RE | USART_CR1_TE | USART_CR1_UE;

    while(1)
    {
        Transmit_Char('A');         //transmit a data
        Delay(1000);
        Blink_Led(1000);
    }
}


 /** @breif: Transmit a character
     * @param: the character to be transmitted
     * @retVal: None
   */

void Transmit_Char(char data)
{
    while (!(USART1->SR & USART_SR_TXE));
    USART1->DR = data & 0xFF;
}


/** @breif: For wait and doing nothing i.e for delay
     * @param: delaya time
     * @retVal: None
   */


    void Delay(int ms)
    {
        int i,j; 
        for (i = 0; i < ms; ++i) {
            for (j = 0; j < 1000; ++j);
            }
    }


 /** @breif: Initalize GPIO For Led
     * @param: None
     * @retVal: None
   */


    void Led_Init()
    {
        LED_PORT_EN();      //Enable RCC for Led Port
        CNF_SET_PORTD(LED_CNF_BIT1,LED_CNF_BIT2);           //SET CNF       General purpose output push-pull
        MODE_SET_PORTD(LED_MODE_BIT1,LED_MODE_BIT2);    //SET MODE  Output mode, max speed 50 MHz. 
    }


 /** @breif: Blink Led Placed in PORT D Pin 2
     * @param: Delay for each state(ON/OFF)
     * @retVal: None
   */


    void Blink_Led(int ms)
    {
        RESET_GPIO_BIT_PORTD(2);    //Make Led High
        Delay(ms);                  //wait
        SET_GPIO_BIT_PORTD(2);      //Make Led Low
        Delay(ms);                  //wait
    }

 /** @breif: Configure PLL 72 MHz
     * @param: None
     * @retVal: None
   */

 void PLL_Config(void)
 {
     Clock_Reset();                     //RESET Clock
     RCC->CR    |=  RCC_CR_HSEON;       //ENABLE HSE

     /* wait till HSE Ready */
     while ( !( RCC->CR & RCC_CR_HSERDY ));

     /* Doubt: Enable Prefetch Buffer */
   /* Doubt: Flash 2 wait state     */   

     HCLK_Config(RCC_CFGR_HPRE_DIV1);   //configure HCLK  AHB clock
     PCLK2_Config(RCC_CFGR_PPRE2_DIV1); //cofigure PCLK2  APB2 clock
     PCLK1_Config(RCC_CFGR_PPRE1_DIV2); //configure PCLK1 APB1 clock
     PLLCLK_Config(RCC_CFGR_PLLSRC, RCC_CFGR_PLLMULL9); //configure PLLCLK 72MHz

     RCC->CR |= RCC_CR_PLLON;   //ENABLE PLL

     /* Wait till PLL is Ready */
     while (!(RCC->CR & RCC_CR_PLLRDY));

     SYSCLK_Config(RCC_CFGR_SW_PLL);

     /* wait till PLL is used as system clock */
     while (!(RCC->CFGR & RCC_CFGR_SWS_PLL));

 }


 /** @breif: Select PLL as system clock source
     * @param: RCC_CFGR_SW_PLL = ((uint32_t)0x00000002)
     * @retVal: None
   */

 void SYSCLK_Config(uint32_t RCC_SYSCLKSource)
 {
        uint32_t tmpreg = 0;

        tmpreg = RCC->CFGR;
        /* Clear SW[1:0] bits */
        tmpreg &= SW_RESET_MASK;
        /* Set SW[1:0] bits according to RCC_SYSCLKSource value */
        tmpreg |= RCC_SYSCLKSource;
        /* Store the new value */
        RCC->CFGR = tmpreg;
 }



 /** @breif: Set PCLK1 = HCLK/2
   *         HCLK divided by 2
     * @param: RCC_CFGR_PLLSRC = ((uint32_t)0x00010000)
   * @param: RCC_CFGR_PLLMULL9 = ((uint32_t)0x001C0000)
     * @retVal: None
   */
 void PLLCLK_Config(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul)
 {
      uint32_t tmpreg = 0;

        tmpreg = RCC->CFGR;
        /* Clear PLLSRC, PLLXTPRE and PLLMUL[3:0] bits */
        tmpreg &= PLLCLK_CONFIG_RESET_MASK;
        /* Set the PLL configuration bits */
        tmpreg |= RCC_PLLSource | RCC_PLLMul;
        /* Store the new value */
        RCC->CFGR = tmpreg;
 }


 /** @breif: Set PCLK1 = HCLK/2
   *         HCLK divided by 2
     * @param: RCC_CFGR_PPRE1_DIV2 = ((uint32_t)0x00000400)
     * @retVal: None
   */ 

 void PCLK1_Config(uint32_t RCC_HCLK)
 {
   uint32_t tmpreg = 0;

   tmpreg = RCC->CFGR;
   /* Clear PPRE1[2:0] bits */
   tmpreg &= PPRE1_RESET_MASK;
   /* Set PPRE1[2:0] bits according to RCC_HCLK value */
   tmpreg |= RCC_HCLK;
   /* Store the new value */
   RCC->CFGR = tmpreg;
 }




 /** @breif: Set PCLK2 = HCLK
   *         HCLK not divided
     * @param: RCC_CFGR_PPRE2_DIV1 = ((uint32_t)0x00000000)
     * @retVal: None
   */ 

 void PCLK2_Config(uint32_t RCC_HCLK)
 {
   uint32_t tmpreg = 0;

   tmpreg = RCC->CFGR;
   /* Clear PPRE2[2:0] bits */
   tmpreg &= PPRE2_RESET_MASK;
   /* Set PPRE2[2:0] bits according to RCC_HCLK value */
   tmpreg |= RCC_HCLK;
   /* Store the new value */
   RCC->CFGR = tmpreg;
 }


 /** @breif: Set HCLK = SYSCLK
   *         SYSCLK not divided
     * @param: RCC_CFGR_HPRE_DIV1 = ((uint32_t)0x00000000)
     * @retVal: None
   */

  void HCLK_Config(uint32_t RCC_SYSCLK)
    {
        uint32_t tmpreg = 0;

        tmpreg = RCC->CFGR;
        /* Clear HPRE[3:0] bits */
        tmpreg &= HPRE_RESET_MASK;
        /* Set HPRE[3:0] bits according to RCC_SYSCLK value */
        tmpreg |= RCC_SYSCLK;
        /* Store the new value */
        RCC->CFGR = tmpreg;
    }



 /** @breif: Resets the Clock
     * @param: None
     * @retVal: None
   */
 void Clock_Reset(void)
 {
   /* Set HSION bit */
   RCC->CR |= (uint32_t)0x00000001;

   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
   RCC->CFGR &= (uint32_t)0xF0FF0000;  

   /* Reset HSEON, CSSON and PLLON bits */
   RCC->CR &= (uint32_t)0xFEF6FFFF;

   /* Reset HSEBYP bit */
   RCC->CR &= (uint32_t)0xFFFBFFFF;

   /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
   RCC->CFGR &= (uint32_t)0xFF80FFFF;

   /* Disable all interrupts and clear pending bits  */
   RCC->CIR = 0x009F0000;
 }

I have few doubts with this code.

  1. Fractional Baud rate generation:

    Formula given is:

    Tx/Rx baud = fclk/(16 * USARTDIV)

    fclk(after pll setup will be 72MHz) : 72MHz

    Tx/Rx Baud required is: 115200

    so USARTDIV = fclk/(16*baud)

    i.e USARTDIV = 72000000/(16*115200) = 39.0625(which is given in Table 192. Error calculation for programmed baud rates)

    Then there is an example question (Example 2) where it says to program USARTDIV as 39.0625(Your USARTDIV)

    DIV_Fraction = 16*0d0.0625 = 0d1 = 0x1

    DIV_Mantissa = mantissa (0d39.0625) = 0d39 = 0x27

    Then, USART_BRR = 0x271

    i have used this value on my USART_BRR register but not getting the correct value.

  2. Is the code correct for Usart tx?

Any suggestions will be really helpful. Because nothing is showing in the terminal i.e usart is not working

Thanks in advance

c
stm32
asked on Stack Overflow Feb 6, 2018 by Devjeet Mandal • edited Feb 14, 2018 by Devjeet Mandal

2 Answers

3

First - do not use "magic numbers" like 1<<7 as ARM uC are to complicated to remember remember bit numbers in the registers.

You have the CMSIS human readable definitions and you should use them.

If if understand correct your question you want to find the moment when the U(S)ART has finished the transmission of the data - to be for example disabled.

The TXE bit in the SR register shows that there is a space in the DR transmit register to put new data. It happens when the previous data has been transmitted to the internal transmit register. It does not mean that the data has been transmitted. You need to check if the TC bit is set before disabling the U(S)ART or entering the halt mode to avoid last data corruption.

CMSIS symbols for those flags are:

USART_SR_TXE
USART_SR_TC

So if you want to check if you can put new data into the DR register you need to check (in your case)

while(!(USART1 -> SR & USART_SR_TXE));

and before disabling the peripheral

while(!(USART1 -> SR & USART_SR_TC));

Answering the second question.

The clock in the table in the RM is 32MHz. Your clock is 8MHz. And that is the problem and why UART does not work. Your real transfer speed is 4 times slower than you think and configure on the other side of the serial calble

answered on Stack Overflow Feb 6, 2018 by 0___________ • edited Feb 6, 2018 by 0___________
0

TX Empty is bit 7 of the USART status register. It looks from your code like you're using USART 1, so your check is simply

while((USART1->SR & (1 << 7)) != (1 << 7));

It would be worth defining a constant somewhere for (1 << 7) when used like this, or using the one which is probably defined in whatever library it is you're using.

answered on Stack Overflow Feb 6, 2018 by Colin

User contributions licensed under CC BY-SA 3.0