cancel
Showing results for 
Search instead for 
Did you mean: 

USART not working

sue
Associate III
Posted on August 16, 2010 at 02:07

USART not working

24 REPLIES 24
Posted on May 17, 2011 at 14:02

I've done USART1 polled from assembler, which worked fine with minimal initialization. I also cleared the prescaler.

While I can't micro analyze your code fragment, and can offer the following quick suggestions.

Make sure you have all you clocks and clock sources set correctly. USART2 runs off the 36 MHZ PCLK1 (APB1), for 9600 baud the divider is surely 0x0EA6 not 0x1D4C

Make sure you have set up the GPIO pins correctly to match the peripheral setting, pin directions, etc.

Have your code stream out a byte or pattern of bytes on USART2, check that you can see this data on HyperTerminal or RealTerm (better). Confirm you can see data, and baud rate is correct. Check also on scope if you get junk.

Have your code do polled input, verify it receives the correct data, or echo back the data so you can see it in your terminal.

Make sure you have initialized the NVIC correctly, you have priorities/groups and interrupt set up correctly, and enabled. Check also the vector address, and the servicing subroutines.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on May 17, 2011 at 14:02

My assembler for USART1 running straight out of the reset time HSI (8MHz) looks like this. Admittedly somewhat cruder in implementation, it was designed to get the job done and allow for bus fault analysis very early in the boot prior to a working C platform.

  408 0000017C         InitUART

                               PROC

  409 0000017C

  410 0000017C 484E            ldr              r0, =0x40021000 ; RCC

  411 0000017E

  412 0000017E         ;                ldr     r1, =0x00000000 ; HSI as clock

  413 0000017E         ;                str     r1, [r0, #4]    ; RCC_CFGR

  414 0000017E

  415 0000017E F244 0104       ldr              r1, =0x00004004 ; USART1EN | IOPAEN (GPIOA)

  416 00000182 6181            str              r1, [r0, #24] ; +24 RCC_APB2ENR

  417 00000184

  418 00000184 484D            ldr              r0, =0x40010800 ; GPIOA

  419 00000186

  420 00000186 494E            ldr              r1, =0x444444B4 ; PA.9 USART1_TX 50MHz AF_PP

  421 00000188 6041            str              r1, [r0, #4] ; +4 GPIOx_CRH

  422 0000018A

  423 0000018A 4843            ldr              r0, =0x40013800 ; UART1

  424 0000018C

  425 0000018C 2100            movs             r1, #0

  426 0000018E 8081            strh             r1, [r0, #4] ;  +4 USART_DR

  427 00000190

  428 00000190 2145            movs             r1, #69     ; 8MHz / 69 == 115200

  429 00000192 8101            strh             r1, [r0, #8] ;  +8 USART_BR

  430 00000194

  431 00000194 F45F 61C0       movs             r1, #0x0600

  432 00000198 8201            strh             r1, [r0, #16] ; +16 USART_CR2 = 0x600

  433 0000019A

  434 0000019A 2100            movs             r1, #0

  435 0000019C 8201            strh             r1, [r0, #16] ; +16 USART_CR2 = 0

  436 0000019E

  437 0000019E 2100            movs             r1, #0

  438 000001A0 8301            strh             r1, [r0, #24] ; +24 USART_GTPR = 0 - Prescaler

  439 000001A2

  440 000001A2 F242 010C       movw             r1, #0x200C ; 8-bit, no parity, enable TX,RX

  441 000001A6 8181            strh             r1, [r0, #12] ; +12 USART_CR1

  442 000001A8

  443 000001A8 F04F 020A       ldr              r2, =10 ; Send 10 pounds

  444 000001AC F8D0 1000

                       iu1     ldr.w            r1, [r0, #0] ; USART->SR

  445 000001B0 F011 0180       ands             r1, #0x80   ; TXE

  446 000001B4 D0FA            beq              iu1

  447 000001B6 F04F 0123       mov              r1, #'#'

  448 000001BA F8C0 1004       str.w            r1, [r0, #4] ; USART->DR

  449 000001BE F1B2 0201       subs.w           r2, r2, #1  ; $1

  450 000001C2 D1F3            bne.n            iu1

  451 000001C4

  452 000001C4 4770            bx               lr

  453 000001C6

  454 000001C6                 ENDP

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
sue
Associate III
Posted on May 17, 2011 at 14:02

Hi clive, many thanks for your reply.

Ok, I have fixed the baud rate.  I did not know that USART2 did not run at 72mHz.  This info is literally buried in tiny italic type in the manual.

I am pretty sure that I have all other settings done correctly, although I have nothing to go on except some C code that you posted in answer to another query on the forum.  There should be a section in the manual that tells you EVERYTHING you have to set up in order to get usart reception and transmission happening.  C programmers are lucky because they have libraries they can use, we assembler programmers have nothing!

The only thing I am not sure of is the priorities/groups you mention.  I am not using the receive or transmit interrupts at the moment so I don't think priorities are relevant and I don't know what a ''group'' is, there is nothing I can see in the STM32F103 Reference Manual referring to groups in this context.  If you can shed some light on this I will know whether I need to do anything with it.

Having fixed the baud rate and cleared the prescaler I have tried again.  This time with the two USARTS connected to each other with a null modem cable.  The TXE flag is being sent on transmission but I am not receiving anything.

Anything you can suggest would be greatly appreciated.

Posted on May 17, 2011 at 14:02

The source clock for the USARTs also manifests in the maximum speeds, USART2 and 3 are limited to 2.25 Mbaud, vs 4.5 Mbaud for USART1. It gets coverage in a couple of places in the STM32 Reference Manual. The C/Library code holds a lot of the details and interplay, so even if you have to code in assembler you should review the library source to see how the device works in practice.

As for debugging the USART, consider sending out a constant stream of characters. Verifying on a scope that the data is correct and has the right rate/form. Stream it to a PC, and/or loopback the TX and RX to confirm. The output of the USART is CMOS 3.x Volts, and is not suitable to direct connection to a PC, you will need a CMOS to RS232 level conversion (MAX232, et al). USART1 is 5V tolerant, not so sure the others. I've mentioned the voltage issues, as I'm not sure if you are using a dev board or some custom hardware.

One additional note on the USARTs is to make sure you check for and clear reception errors (by reading the data register). If you just look at RXNE it has the potential to stay low, while other errors are pending.

With Keil I can certainly step through all the of C and assembler code, and view the peripheral states/settings. You might want to step your way through the code to make sure nothing is faulting.

The NVIC allows you to group together interrupts of similar priority (with a programmable mask), so they won't preempt each other, the configuration is rather flexible. One gotcha in the implementation is not to give any interrupts within a group the same sub-priority, easy to do if you cut-n-paste code.

http://www.codextr.com/migrating-arm7-code-to-a-cortex-m3-mcu-1/

In the C portion of my system using all 3 USARTs the NVIC configuration looks like this. The interrupt routines themselves do little more than check the assorted status and move data to/from software buffers.

void NVIC_Configuration(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

  u8 Priority;

  NVIC_SetVectorTable((u32)(&__Vectors), 0x0); // Smart Base Location

  /* Configure the NVIC Preemption Priority Bits */

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  Priority = 0;

  /* Enable the USART3 Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQChannel;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = Priority++;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

  /* Enable the USART2 Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQChannel;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = Priority++;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

  /* Enable the USART1 Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = Priority++;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

  /* SysTick is a SubPriority 3 - Handled elsewhere*/

  SysTickPriority = Priority++;

  /* Enable the EXTI Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = Priority++;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

  /* Enable the RTC Alarm Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQChannel;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = Priority++;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
sue
Associate III
Posted on May 17, 2011 at 14:02

Hi Clive, many thanks for your post.

I am using the STM32F103ZE development board with IAR Embedded Workbench IDE.

My project is to receive data over USART2 and USART3 and send data out on USART1.

As I am not a C programmer, looking at C code does not help me.  I did do this but just got more confused.  I cannot even get the Hyperterm Interrupt example  that came with the Standard Peripheral Library to work.

Below are the register settings I am making.  As there is no guidance in the STM32F103 Reference Manual as to exactly what registers you have to deal with when using the USARTS I have had to glean what I know from posts in C on this forum.  As I don't know what I don't know there may be other registers I have to set.

If you can run your eye over this list and maybe tell me what I am missing it will enable me to move forward

I am not using interrupts at this stage, just polling.

;reset_and_clock_control

;    clock_control_register

;        internal high-speed clock enable HSION  on.

;    clock_configuration_register

;        select HSI as system clock

;    apb2_periph_clock_enable_register

;        USART1EN - usart1 clock enable

;        IO port B clock enable (IOPBEN)

;        IO port A clock enable (IOPAEN)

;        alternate function IO clock enable (AFIOEN)

;    apb1_periph_clock_enable_register

;        USART3EN - usart3 clock enable

;        USART2EN - usart2 clock enable  

       

;gpio_port_b

;    port_configuration_register_high   ; configures pins 8 to 15

;        pin 11 configuration - 01 (INPUT MODE: = floating input USART3)

      

;gpio_port_a

;    ort_configuration_register_high   ; configures pins 8 to 15

;        pin 09 configuration - 10 (OUTPUT MODE: = alternate function output push-pull, MODE 11 = 50 mHz USART1)

;gpio_port_a

;    port_configuration_register_low    ; configures pins 0 t0 7

;        pin 03 configuration - 01 (INPUT MODE: = floating input USART2)

;usart1  

;    usart_cr1             

;     UE      - USART enable - on

;     TE      - transmitter enable - on

;usart2  

;    usart_cr1    

;        UE      - USART enable - on

;usart3

;    usart_cr1    

;        UE      - USART enable - on

;usart1

;    usart_cr2           ; control register 2

;        STOP = 0         (1 stop bit)

;usart2

;    usart_cr2           ; control register 2

;        STOP = 0         (1 stop bit)

;usart3

;    uart_cr2           ; control register 2

;         STOP = 0         (1 stop bit)

;usart1

;    usart_brr

;        0x1d4c (9600)

;    usart_dr               

;        0

;    usart_guardtime_prescaler_register

;        0

     

;usart2

;    usart_brr

;        0x0ea6 (9600)

;    usart_dr               

;        0

;    usart_guardtime_prescaler_register

;        0

     

;usart3

;    usart_brr

;        0x1d4c (9600)

;    usart_dr               

;        0

;    usart_guardtime_prescaler_register

;        0

     

;usart2    

;    usart_cr1                ; control register 1

;        RE      - receiver enable - on

;usart3

;    usart_cr1                ; control register 1

;        RE      - receiver enable - on

Posted on May 17, 2011 at 14:02

Ok, if your source clock is HSI, and your AHB, APB1, and APB2 prescalers are 1, then the source frequency to USART1,2,3 is 8 MHz, as is SYSCLK.

The baud rate computation would then be

8000000 / 9600 = 833.333 or 0x0341

or for 115200 baud

8000000 / 115200 = 69 or 0x0045 (see assembler above for how I had USART1 doing this directly out of reset)

With an oscilloscope you could measure the bit time of a pattern like 0x55 if you wanted secondary confirmation that the baud rate was set as expected.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on May 17, 2011 at 14:02

http://www.iar.com/website1/1.0.1.0/658/1/?item=prod_prod-s1%2F255

http://www.iar.com/website1/50.0.1.0/255/IAR_STM32F103ZE_SK.pdf

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
sue
Associate III
Posted on May 17, 2011 at 14:02

Hi Clive, thanks for your reply, but...

Am I wrong, or in your assembler code you refer to are the prescalers not set to zero?  I did as you advised in an earlier post and set the prescalers in my code to zero.  So I am a bit confused.

However, having now set them to 1, and changed the baud rate calculation, for all three usarts the receive is working (using usart2) (yeehaaa) but send is not (using usart1).  Is there anything different I have to do for send? 

Posted on May 17, 2011 at 14:02

The prescalers are clock divider chains designed to efficiently reduce the clock speed. To understand how they fit in you need to look at the clock distribution/gating diagram in the STM32 Reference Manual.

http://www.st.com/stonline/products/literature/rm/13902.pdf

pg 84

At reset the STM32 starts up running from the 8 MHz HSI clock. And the bus prescalers are set to divide-by-1 as RCC_CFGR is zeroed. So you can assume SYSCLK, HCLK, PCLK1 and PCLK2 are 8 MHz at reset time. Unless you reconfigure them they will stay this way.

The programmable divider circuit in the USART derives from PCLK1 or PCLK2, and gets you to the desired baud rate. To know what divider value to use depends on the speed of those clocks, and if you subsequently change to using the PLL and adjust the system and bus clocks you will need to change the baud rate divider to match the new configuration.

There is another prescaler within the USART, it resets to zero.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..