STM32VL Usart counter

Status
Not open for further replies.

Feco

Newbie level 6
Joined
May 13, 2013
Messages
12
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,371
Hello. I'm a beginner at microcontroller programming. I have an STM32VL Discovery board and I made a simple program that counts up and sends the values via USART. I thought it's an easy task. Well the program is working, but I am getting wrong data. On the serial monitor I see the ASCII characters, not the numbers. How can I change it? I want it to show the numbers, not the ASCII.

Here is my code:
Code:
#include <stm32f10x.h>

int n = 0;

void usart_snd(int data) {
    while(!(USART1->SR & USART_SR_TXE));
    USART1->DR = data;
}

void usart_snd_str(char *str) {
    while(*str != 0) {
        usart_snd(*str);
        str++;
    }
}

int main() {
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_IOPAEN;
    RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;

    GPIOA->CRH = 0x4B0;

    USART1->BRR = (SystemCoreClock/9600);
    USART1->CR1 = USART_CR1_UE | USART_CR1_TE;

    TIM3->PSC = 23999;
    TIM3->ARR = 1000;
    TIM3->CR1 = TIM_CR1_CEN;

    while(1) {
        if (TIM3->SR & TIM_SR_UIF) {
            TIM3->SR &= ~TIM_SR_UIF;
            usart_snd_str("Count:\t");
            usart_snd(n);
            usart_snd_str("\n\r");
            n++;
        }
    }
}

Well, it's working if I change n=0 to n=48 but it still only counts until 9, so it wouldn't be the best solution.

Thanks for the help.
 

On the serial monitor I see the ASCII characters, not the numbers. How can I change it? I want it to show the numbers, not the ASCII.

Your above statements actually contain the clue as to why the output is not what you expected.

Terminal emulation programs like Hyperterminal, Putty, etc, interpret the received bytes of data as ASCII characters, not numerical values.

Therefore to display the received data as numerical data, rather than ASCII characters, you must first convert the numerical value to an ASCII character string.

For example, the numerical value 32535 would need to be converted to a character string of '3''2''5''3''5' or "32535".

There are several ways to achieve this including writing your own routine, which your following statement touches on:

Well, it's working if I change n=0 to n=48 but it still only counts until 9, so it wouldn't be the best solution.

However, as you pointed out above, you must first separate the numerical values digits before converting them to ASCII characters.

If you search the forum you will find numerous methods of achieve this task.

Fortunately, the C Standard Library provides the sprintf() routine which accomplishes this task quite nicely.

int sprintf(char *str, const char *format, ...)

Code:
#include <stdio.h>
#include <math.h>

int main()
{
   char str[80];

   sprintf(str, "Value of Pi = %f", M_PI);
   puts(str);
   
   return(0);
}

The sprintf() routine can consume large amounts of code storage, making its utilization in some cases, particularly with embedded systems, less than ideal.

Which is why many embedded programmers prefer to utilize their own routines to save code storage (Flash) and increase performance.


BigDog
 
Reactions: Feco

    Feco

    Points: 2
    Helpful Answer Positive Rating
It's working fine, thx.
 

Hey there.

Now I have a new, but similar problem. I wanted to receive data via USART. I have a seven-segment display and if I press '0' then it should show 0, if '1' then 1 .... if '9' then 9.
But it show strange things. The wrong LEDs are lighting. I figured out if I press '@' then it show 0, if 'A' then 1 .... if 'I' then 9. I really don't know why.. Maybe do you have any suggestion?

Here is the code:
Code:
#include <stm32f10x.h>

int n;
int digits[10] = {0B00000011,  // = 0
                  0B10011111,  // = 1
                  0B00100101,  // = 2
                  0B00001101,  // = 3
                  0B10011001,  // = 4
                  0B01001001,  // = 5
                  0B01000001,  // = 6
                  0B00011111,  // = 7
                  0B00000001,  // = 8
                  0B00001001}; // = 9


int USART_rec(void) {
    while(!(USART1->SR & USART_SR_RXNE));
    return USART1->DR & 0x1FF;
}

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

void USART_snd_str(char *str) {
    while(*str != 0) {
        USART_snd(*str);
        str++;
    }
}

int main(void) {
    RCC->APB2ENR = RCC_APB2ENR_USART1EN | RCC_APB2ENR_IOPAEN;

    USART1->BRR = SystemCoreClock/9600;
    USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;

    GPIOA->CRL = 0x11111111;
    GPIOA->CRH = 0x490;

    while(1) {
        n = USART_rec();
        GPIOA->ODR = digits[n];
        USART_snd(n);
    }
}
 

Now you need to reverse the process, convert the received ASCII character back to a simple numerical value before using it to index the 7-Segment Display array, digits[].

In other words, when the ASCII character for '1' is received, the corresponding numerical value is 0x31, which needs to be converted to 0x01.

The ASCII character for '8' is received, the corresponding numerical value is 0x38, which needs to be converted to 0x08.

And so on and so forth.

You have already discussed the necessary conversion process in your first post.


You also might want to check the range of the received ASCII character and make sure it is a numerical character, '0' to '9', otherwise and error character can be display instead.


BigDog
 
Reactions: Feco

    Feco

    Points: 2
    Helpful Answer Positive Rating
Thank you.
 

Hi,

Use hercules serial Port application in your PC instead of Terminal monitor and it has capacity to display or send both ASCII value as hex value.

Regards,
Ghanshyam
gvshyam1682 - At-gmail-dot-com.
 
Reactions: Feco

    Feco

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…