Help with Olimex STM32_P103 UART2

Hi,

I’ve been trying to use my P103 Dev board from Olimex (http://olimex.com/dev/stm32-p103.html) to communicate via serial to my computer, but I’ve been having some issues. As far as I can tell, because there’s no clock, the computer is incorrectly reading the data from the chip. For example, I’ll send “:” (0x3a), but the computer will read “e”. But only sometimes, other times it’ll read random characters, but on the whole it’s somewhat consistent. Anyway, I’ve experimented with a few different settings - Baud Rate, Parity, Stop bits - but can’t make it function properly.

My code is as follows:

Computer-side:

#include "StdAfx.h"

int main(void){
HANDLE hSerial;
hSerial = CreateFileA("COM1",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if(hSerial==INVALID_HANDLE_VALUE){
if(GetLastError()==ERROR_FILE_NOT_FOUND){
//serial port does not exist. Inform user.
}
//some other error occurred. Inform user.
}
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
if (!GetCommState(hSerial, &dcbSerialParams)) {
//error getting state
}
dcbSerialParams.BaudRate=CBR_19200;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
if(!SetCommState(hSerial, &dcbSerialParams)){
//error setting serial port state
}
COMMTIMEOUTS timeouts={0};
timeouts.ReadIntervalTimeout=50;
timeouts.ReadTotalTimeoutConstant=50;
timeouts.ReadTotalTimeoutMultiplier=10;
timeouts.WriteTotalTimeoutConstant=50;
timeouts.WriteTotalTimeoutMultiplier=10;
if(!SetCommTimeouts(hSerial, &timeouts)){
//error occureed. Inform user
}
char szBuff[10] = {0};
DWORD dwBytesRead = 0;
if(!ReadFile(hSerial, szBuff, 9, &dwBytesRead, NULL)){
printf("fail");
}
int i = 0;
while(i<11){
	printf(""+szBuff[i]);
	i++;
}
CloseHandle(hSerial);
return 0;
}

STM32-side (main.c):

/*
 * main.c
 *
 *  Created on: Aug 6, 2010
 *      Author: icecube
 */

#include "stm32f10x_lib.h"
#include "stm32f10x_map.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_usart.h"
#include "bits.h"
#include "stm32f10x_usart.c"
#include "usart.c"

#define STACK_TOP 0x20000800
#define NVIC_CCR ((volatile unsigned long *)(0xE000ED14))

int main(void);
void myDelay(unsigned long delay );
void Clk_Init(void);
// Define the vector table
	unsigned int * myvectors[4]
     __attribute__ ((section("vectors")))= {
   	(unsigned int *)	0x20000800,	// stack pointer
   	(unsigned int *) 	main,		// code entry point
};
int main(void) {
	*NVIC_CCR = *NVIC_CCR | 0x200; /* Set STKALIGN in NVIC */
// Init clock system
  Clk_Init();

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOA, ENABLE);


        // Configure PC.12 as output push-pull (LED)
        GPIO_WriteBit(GPIOC,GPIO_Pin_12,Bit_SET);
        GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_12;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOC, &GPIO_InitStructure);

InitUSART2();

            GPIOC->BRR |= 0x00001000;
            myDelay(1500000);
            GPIOC->BSRR |= 0x00001000;


	int i = 100;
	while(1){
		Uart2SendChar(0x3a);
	}
}
void myDelay(unsigned long delay )
{
  while(delay) delay--;
}

void Clk_Init (void)
{
  // 1. Cloking the controller from internal HSI RC (8 MHz)
  RCC_HSICmd(ENABLE);
  // wait until the HSI is ready
  while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
  RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
  // 2. Enable ext. high frequency OSC
  RCC_HSEConfig(RCC_HSE_ON);
  // wait until the HSE is ready
  while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
  // 3. Init PLL
  RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); // 72MHz
//  RCC_PLLConfig(RCC_PLLSource_HSE_Div2,RCC_PLLMul_9); // 72MHz
  RCC_PLLCmd(ENABLE);
  // wait until the PLL is ready
  while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
  // 4. Set system clock divders
  RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);
  RCC_ADCCLKConfig(RCC_PCLK2_Div8);
  RCC_PCLK2Config(RCC_HCLK_Div1);
  RCC_PCLK1Config(RCC_HCLK_Div2);
  RCC_HCLKConfig(RCC_SYSCLK_Div1);
  // Flash 1 wait state
  *(vu32 *)0x40022000 = 0x12;
  // 5. Clock system from PLL
  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
}

usart.c:

........
void InitUSART2(void) {

  // Enable clocks
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

  USART_Cmd(USART2, ENABLE);

  // Gonfigure UART2_Tx pin PA2
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init (GPIOA, &GPIO_InitStructure);

  // Gonfigure UART2_Rx pin PA3
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD ;
  GPIO_Init (GPIOA, &GPIO_InitStructure);


  USART_StructInit(&USART_InitStructure);
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_BaudRate = 19200;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = (USART_Mode_Tx | USART_Mode_Rx);


  USART_Init(USART2, &USART_InitStructure);

}
......
void Uart2SendChar(Int8U c) {

  while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
  USART_SendData(USART2, c);
}

Here’s a screenshot of the result:

http://i6.photobucket.com/albums/y225/m … mdshot.jpg

I’d really appreciate help with this. Thanks in advance.

Symptoms suggest

the UART baud rate divisor is not being calculated/applied correctly and/or

CPU PLL not set to yield the frequency you think it is

assuming the wiring and jumpers and RS232 level converters are correct and

the PC side baud rate, etc is correct

this

while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
  USART_SendData(USART2, c);

looks suspicious to me. I’ve not worked with ST (ony NXP) but the == RESET seems wrong. Shouldn’t this be checking for the UART transmit holding register empty bit being true? And there’s the issue of if you have turned on the FIFO. the constant RESET is what?

Suggestion… code is easier to read if

while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
   {}; // loop until condition is true
USART_SendData(USART2, c);