Skip to main content
henk2
Associate II
September 8, 2010
Question

ST32F103ZE USART not receiving?

  • September 8, 2010
  • 11 replies
  • 2125 views
Posted on September 08, 2010 at 13:08

ST32F103ZE USART not receiving?

    This topic has been closed for replies.

    11 replies

    henk2
    henk2Author
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:06

    Hi answerers,

    somehow all replies have disappeared?

    There were about 5 replies but now all gone?

    Some ST-server error?

    Henk

    henk2
    henk2Author
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:06

    Weird things happening here...or was it because I replied to someone that was not the last post in my thread maybe?

    Well anyway.

    There was a question if I had switched on the APBn clock: I did.

    Another question of about some signal which is not available on the STM32F103ZE.

    Another question was if I had poweredup.

    The only thing I found is that the Alternate Function I/O Clock was not enabled but after enabling it the receiver still does not receive anything.

    Henk

    Tesla DeLorean
    Guru
    May 17, 2011
    Posted on May 17, 2011 at 14:06

    That seems to a lot of replies to be missing for a topic that has been open for 5 hours, and didn't appear to have any responses 2 hours ago.

    Suspect you were looking at another painfully similar thread.

    Post some code so we don't have guess what you ended up with.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    henk2
    henk2Author
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:06

    Hi,

    I think I must apologize, I'm getting old, posting also on the

    http://www.keil.com/

    forum busy answering my browser collapsed, I had a meeting and afterwards I logged in on

    http://www.st.com/

    and found my postings were gone... ;)

    But anyway after 8 hours of puzzling my receiver still does not work. I think indeed it must be something with the initialisaton sequence.

    I rewrote my code from ASAURT2 to USART1:

    [code]

    //include all general system header file (clock divider e.t.c.)

    #include <stm32f10x.h>

    //============================================================

    // USART1 IRQ HANDLER

    //============================================================

    void USART1_IRQHandler(void){

     //put test pattern on board leds

     GPIOB->ODR=0x00005500;

     //disable USART1 global interrupt

     NVIC->ISER[1]|=~NVIC_ISER_SETENA_5;

     //wait here

     for(;;){}

    }//event

    //============================================================

    //      MAIN

    //============================================================

    int main(void){

     //enable the GPIO clock for port GPIOA

     RCC->APB2ENR|=RCC_APB2ENR_IOPAEN;

     //enable the GPIO clock for port GPIOB

     RCC->APB2ENR|=RCC_APB2ENR_IOPBEN;

     //put test pattern on onboard leds

     GPIOB->ODR=0x00005a00;

     //------------------------------

     // AHB prescaler clock setting

     //------------------------------

     //set the AHB prescaler divisor to 1 (so input frequency = 8.000.000 / 1 = 8.000.000Hz)

     RCC->CFGR=(RCC->CFGR&~RCC_CFGR_HPRE)|RCC_CFGR_HPRE_DIV1;

     //------------------------------

     // APB1 prescaler clock setting

     //------------------------------

     //set the ABP1 prescaler for timers divisor to 8 (so input frequency = 8.000.000 / 8 = 1.000.000Hz)

     RCC->CFGR=(RCC->CFGR&~RCC_CFGR_PPRE1)|RCC_CFGR_PPRE1_DIV1;

     //------------------------------

     // APB2 prescaler clock setting

     //------------------------------

     //set the ABP2 prescaler for timers divisor to 8 (so input frequency = 8.000.000 / 8 = 1.000.000Hz)

     RCC->CFGR=(RCC->CFGR&~RCC_CFGR_PPRE2)|RCC_CFGR_PPRE2_DIV1;

     //------------------------------

     // Experiment to reset USART1

     //------------------------------

     //reset usart1

     RCC->APB2RSTR|=RCC_APB2RSTR_USART1RST;

     //unreset usart1

     RCC->APB2RSTR&=~RCC_APB2RSTR_USART1RST;

     //------------------------------

     // USART1 peripheral clock enable

     //------------------------------

     //enable the USART1 peripheral clock

     RCC->APB2ENR|=RCC_APB2ENR_USART1EN;

     //------------------------------

     // Alternate function io enable

     //------------------------------

     //alternate function io enable

     RCC->APB2ENR|=RCC_APB2ENR_AFIOEN;

     //------------------------------

     //  PA09 (TX) is Alternate Output Push Pull + PA10 (RX) input float

     //------------------------------

     //PA09 is Alternate Output Push Pull + PA10 input float

     GPIOA->CRH=0x000004b0;

     //------------------------------

      //  numbered settings are according reference manual pdf

     //------------------------------

     // 1. Enable the USART by writing the UE bit in USART_CR1 register to 1.

     USART1->CR1|=USART_CR1_UE;

     // 2. Program the M bit in USART_CR1 to define the word length.(bit is 0 => 8bits)

     USART1->CR1&=~USART_CR1_M;

     // 3. Program the number of stop bits in USART_CR2. (both bits are 0 => 1 stopbit)

     USART1->CR2=(USART1->CR2&~USART_CR2_STOP)|(~USART_CR2_STOP_1&~USART_CR2_STOP_0);

     // 4. Select DMA enable (DMAR) in USART_CR3 if multibuffer communication is to take

     //    place. Configure the DMA register as explained in multibuffer communication. STEP 3

     // 5. Select the desired baud rate using the baud rate register USART_BRR (115200 baud)

     USART1->BRR=8000000/115200;

     // 6. Set the RE bit USART_CR1. This enables the receiver which begins searching for a

     //    start bit.

     USART1->CR1|=USART_CR1_RE;

     //enable receive-data interrupt

     USART1->CR1|=USART_CR1_RXNEIE;

     //----------------------------------------

     // to enable the USART1 interrupt

     // the corresponding bit must be set

     // in the ISER register

     //enable USART1 global interrupt

     NVIC->ISER[1]=NVIC_ISER_SETENA_5;

     //debug test: force a pending usart1 interrupt

     //NVIC->ISPR[1]=NVIC_ISPR_SETPEND_5;

     //forever do...

     for(;;){

     

      //read and show the status register

      vShowByteXByOnboardLeds(USART1->SR&0x000000ff);

     }//for

    }//main

    [/code]

    Ahum, there's no preview option on this forum I think so I just paste my code here.

    Henk

    Tesla DeLorean
    Guru
    May 17, 2011
    Posted on May 17, 2011 at 14:06

    The forum is certainly a hunk-of-junk, and has eaten a fair amount of my posts.

    AFIO only becomes critical if you start remapping peripherals.

    USART2 is on a different peripheral bus than USART1, but USART1,2,3 all work quite fine.

    Clocks need to be running to peripherals before you configure them. Once the peripherals are configured, you can enable the peripherals. The sequence of things can be important.

    Please attach your code if you want someone to review it. Note tool chain you are using.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Tesla DeLorean
    Guru
    May 17, 2011
    Posted on May 17, 2011 at 14:06

    The following lines have issues (don't do what you say they should)

     //disable USART1 global interrupt

     NVIC->ISER[1]|=~NVIC_ISER_SETENA_5;

    // 3. Program the number of stop bits in USART_CR2. (both bits are 0 => 1 stopbit)

     USART1->CR2=(USART1->CR2&~USART_CR2_STOP)|(~USART_CR2_STOP_1&~USART_CR2_STOP_0);

    There are some other ordering issues, I'm cleaning up now, and it doesn't initialize GPIOB for output.

    Step One, try doing this without interrupts. I use the ST Library to initialize the NVIC, I'm not convinced you have enough code to initialize it properly (ie address grouping, priority, etc).

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Tesla DeLorean
    Guru
    May 17, 2011
    Posted on May 17, 2011 at 14:06

    #include ''stm32f10x.h''

    int main(void)

    {

      // At Reset STM32 runs off 8 MHz HSI, prescalers are 1, ie all clocks @ 8 MHz

     //------------------------------

     // AHB prescaler clock setting

     //------------------------------

     //set the AHB prescaler divisor to 1 (so input frequency = 8.000.000 / 1 = 8.000.000Hz)

     RCC->CFGR=(RCC->CFGR&~RCC_CFGR_HPRE)|RCC_CFGR_HPRE_DIV1;

     //------------------------------

     // APB1 prescaler clock setting

     //------------------------------

     //set the ABP1 prescaler for timers divisor to 8 (so input frequency = 8.000.000 / 8 = 1.000.000Hz)

     RCC->CFGR=(RCC->CFGR&~RCC_CFGR_PPRE1)|RCC_CFGR_PPRE1_DIV1;

     //------------------------------

     // APB2 prescaler clock setting

     //------------------------------

     //set the ABP2 prescaler for timers divisor to 8 (so input frequency = 8.000.000 / 8 = 1.000.000Hz)

     RCC->CFGR=(RCC->CFGR&~RCC_CFGR_PPRE2)|RCC_CFGR_PPRE2_DIV1;

      // Could consolidate these

     //enable the GPIO clock for port GPIOA

     RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;

     //enable the GPIO clock for port GPIOB

     RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;

     //alternate function io enable

     RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

     //enable the USART1 peripheral clock

     RCC->APB2ENR |= RCC_APB2ENR_USART1EN;

     //------------------------------

     //  PA09 (TX) is Alternate Output Push Pull + PA10 (RX) input float

     //------------------------------

     //PA09 is Alternate Output Push Pull + PA10 input float

     GPIOA->CRH = (GPIOA->CRH & 0xFFFFF00F) | 0x000004B0;

     // Set up GPIOB Bits PB.8 thru 15 push-pull 2 MHz, Default to input floating

     GPIOB->CRH = 0x22222222;

     //put test pattern on onboard leds

     GPIOB->ODR = 0x00005A00;

     //------------------------------

     // Experiment to reset USART1

     //------------------------------

     //reset usart1

     RCC->APB2RSTR |= RCC_APB2RSTR_USART1RST;

     //unreset usart1

     RCC->APB2RSTR &= ~RCC_APB2RSTR_USART1RST;

     // I would program CR1,CR2 and BRR in three single operations

      //  USART1->BRR = 8000000/115200;

      //  USART1->CR1 = 0x200C; // Enable USART,TX,RX

     //  USART1->CR2 = 0x0000;

     // 115200 8-N-1

     //------------------------------

      //  numbered settings are according reference manual pdf

     //------------------------------

     // 1. Enable the USART by writing the UE bit in USART_CR1 register to 1.

     USART1->CR1 |= USART_CR1_UE;

     // 2. Program the M bit in USART_CR1 to define the word length.(bit is 0 => 8bits)

     USART1->CR1 &= ~USART_CR1_M;

     // 3. Program the number of stop bits in USART_CR2. (both bits are 0 => 1 stopbit)

     USART1->CR2 &= ~USART_CR2_STOP;

     // 4. Select DMA enable (DMAR) in USART_CR3 if multibuffer communication is to take

     //    place. Configure the DMA register as explained in multibuffer communication. STEP 3

     // 5. Select the desired baud rate using the baud rate register USART_BRR (115200 baud)

     USART1->BRR = 8000000/115200;

     // 6. Set the RE bit USART_CR1. This enables the receiver which begins searching for a

     //    start bit.

     USART1->CR1 |= USART_CR1_RE;

     // Simple Rx loop to GPIOB / LEDS

     while(1)

     {

       if (USART1->SR & 0x20) // RXF

         GPIOB->ODR = (USART1->DR & 0xFF) << 8;

     }

    }

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    henk2
    henk2Author
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:06

    Hi,

    >//disable USART1 global interrupt

    > NVIC->ISER[1]|=~NVIC_ISER_SETENA_5;

    You'r right it should be '&=' not '|='

    >// 3. Program the number of stop bits in USART_CR2. (both bits are 0 => 1 stopbit)

    > USART1->CR2=(USART1->CR2&~USART_CR2_STOP)

    >|(~USART_CR2_STOP_1&~USART_CR2_STOP_0);

    I thought this was okay although a little expanded:

    (A) = (USART1->CR2&~USART_CR2_STOP) will clear bits 12 and 13 in a copy of CR2 to make room for eventually setting both bits

    (B) = (~USART_CR2_STOP_1&~USART_CR2_STOP_0) will also clear bits 12 and 13 (or set one or both if needed)

    So USART1->CR2=(A) | (B) will clear bits 12 and 13 of CR2 meaning using 1 stopbit.

    Thanks for reviewing my program, tomorrow being at my company I will give it a try.

    Henk

    Tesla DeLorean
    Guru
    May 17, 2011
    Posted on May 17, 2011 at 14:06

    For an interrupt, the following example also works.

    #include ''stm32f10x.h''

    void USART1_IRQHandler(void)

    {

       if (USART1->SR & 0x20) // RXF

       {

         int i;

         i = USART1->DR & 0xFF; // Read and clear pending RX IRQ

         GPIOB->ODR = i << 8; // Led

         USART1->DR = i; // Echo

       }

    }

    int main(void)

    {

      // At Reset STM32 runs off 8 MHz HSI, prescalers are 1, ie all clocks @ 8 MHz

     //------------------------------

     // AHB prescaler clock setting

     //------------------------------

     //set the AHB prescaler divisor to 1 (so input frequency = 8.000.000 / 1 = 8.000.000Hz)

     RCC->CFGR=(RCC->CFGR&~RCC_CFGR_HPRE)|RCC_CFGR_HPRE_DIV1;

     //------------------------------

     // APB1 prescaler clock setting

     //------------------------------

     //set the ABP1 prescaler for timers divisor to 8 (so input frequency = 8.000.000 / 8 = 1.000.000Hz)

     RCC->CFGR=(RCC->CFGR&~RCC_CFGR_PPRE1)|RCC_CFGR_PPRE1_DIV1;

     //------------------------------

     // APB2 prescaler clock setting

     //------------------------------

     //set the ABP2 prescaler for timers divisor to 8 (so input frequency = 8.000.000 / 8 = 1.000.000Hz)

     RCC->CFGR=(RCC->CFGR&~RCC_CFGR_PPRE2)|RCC_CFGR_PPRE2_DIV1;

      // Could consolidate these

     //enable the GPIO clock for port GPIOA

     RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;

     //enable the GPIO clock for port GPIOB

     RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;

     //alternate function io enable

     RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

     //enable the USART1 peripheral clock

     RCC->APB2ENR |= RCC_APB2ENR_USART1EN;

     //------------------------------

     //  PA09 (TX) is Alternate Output Push Pull + PA10 (RX) input float

     //------------------------------

     //PA09 is Alternate Output Push Pull + PA10 input float

     GPIOA->CRH = (GPIOA->CRH & 0xFFFFF00F) | 0x000004B0;

     // Set up GPIOB Bits PB.8 thru 15 push-pull 2 MHz, Default to input floating

     GPIOB->CRH = 0x22222222;

     //put test pattern on onboard leds

     GPIOB->ODR = 0x00005A00;

     //------------------------------

     // Experiment to reset USART1

     //------------------------------

     //reset usart1

     RCC->APB2RSTR |= RCC_APB2RSTR_USART1RST;

     //unreset usart1

     RCC->APB2RSTR &= ~RCC_APB2RSTR_USART1RST;

     // I would program CR1,CR2 and BRR in three single operations

      //  USART1->BRR = 8000000/115200;

      //  USART1->CR1 = 0x200C; // Enable USART,TX,RX

     //  USART1->CR2 = 0x0000;

     // 115200 8-N-1

     //------------------------------

      //  numbered settings are according reference manual pdf

     //------------------------------

     // 1. Enable the USART by writing the UE bit in USART_CR1 register to 1.

     USART1->CR1 |= USART_CR1_UE;

     // 2. Program the M bit in USART_CR1 to define the word length.(bit is 0 => 8bits)

     USART1->CR1 &= ~USART_CR1_M;

     // 3. Program the number of stop bits in USART_CR2. (both bits are 0 => 1 stopbit)

     USART1->CR2 &= ~USART_CR2_STOP;

     // 4. Select DMA enable (DMAR) in USART_CR3 if multibuffer communication is to take

     //    place. Configure the DMA register as explained in multibuffer communication. STEP 3

     // 5. Select the desired baud rate using the baud rate register USART_BRR (115200 baud)

     USART1->BRR = 8000000/115200;

     // 6. Set the RE bit USART_CR1. This enables the receiver which begins searching for a

     //    start bit.

     USART1->CR1 |= USART_CR1_RE;

      // enable transmit for echo back

     USART1->CR1 |= USART_CR1_TE;

     //enable receive-data interrupt

     USART1->CR1 |= USART_CR1_RXNEIE;

     //----------------------------------------

     // to enable the USART1 interrupt

     // the corresponding bit must be set

     // in the ISER register

     //enable USART1 global interrupt

     NVIC->ISER[1] = NVIC_ISER_SETENA_5;

     while(1); // Forever

    }

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    henk2
    henk2Author
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 14:06

    Hi dive1,

    Your program works!

    I didn't read your last post until now starting to reply.

    I compared your program to mine step by step.

    It turned out only to be the stopbit setting.

    Your conclusion is right.

    What I replied about 'or-ing' is completely bullshit. (apollogize)

    I changed the '|' by '&' and my program also runs.

    Now I'v a headache because I hit myself with a hammer ten times on my head.

    8 hours spend on such a STUPID failure. (@*@

    mailto:&@^#*&%

    #)

    But beneath that I learned a lot about the clocks and sequences. (didn't know that the AF clock also should be enabled e.t.c.)

    It was your program that helped me out.

    so THANKS!

    Henk