STM32f4. Функция atoi.

Все о микроконтроллерах: AVR, PIC, STM8, STM32, Arduino, Altera, Xilinx, все что угодно. Этот раздел для всего что клацает байтиками.
Rogers
Сообщения: 13
Откуда: МО, Климовск

Сообщение Rogers » 26 сен 2014, 16:01

Приветствую! Я продолжаю ковырять тему UARTа и у меня появился вопрос: как полученные данные (строка) переконвертировать в числовые данные? То есть ввожу "0" (в терминале) как "строку" (30 в hex коде), а в результате хочу вывести "0" как число (0 в hex коде). И как это отследить/проверить ? В различных терминалах уже сразу конвертируется результат ввода/вывода в ASCII/Hex. Про функцию atoi я в курсе и использовал ее в windows-приложениях, но не в arm. Прикладываю рабочий код по приему "строки" и вывода "строки". Работаю в keil 5.0.

Код: Выделить всё

#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_usart.h"


char uart2_rx_buf[128]; //Буфер для приёма сообщения.
uint8_t uart2_rx_bit; //Номер байта UART принимаемого в буфер.


//Функция отправляет байт в UART
void send_to_uart(uint8_t data)
{
 while(!(USART2->SR & USART_SR_TC));
 USART2->DR=data;
}

//Функция отправляет строку в UART, по сути пересылая по байту в send_to_uart
void send_str(char * string)
{
 uint8_t i=0;
 while(string[i])
 {
  send_to_uart(string[i]);
  i++;
 }
}

//Инициализируем USART2
void usart_init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure; //Структура содержащая настройки порта
  USART_InitTypeDef USART_InitStructure; //Структура содержащая настройки USART

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //Включаем тактирование порта A
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //Включаем тактирование порта USART2


  GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); //Подключаем PA3 к TX USART2
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); //Подключаем PA2 к RX USART2

  //Конфигурируем PA2 как альтернативную функцию -> TX UART. Подробнее об конфигурации можно почитать во втором уроке.
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  //Конфигурируем PA2 как альтернативную функцию -> RX UART. Подробнее об конфигурации можно почитать во втором уроке.
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  USART_StructInit(&USART_InitStructure); //Инициализируем UART с дефолтными настройками: скорость 9600, 8 бит данных, 1 стоп бит

  USART_Init(USART2, &USART_InitStructure);
  USART_Cmd(USART2, ENABLE); //Включаем UART
}

int main(void)
{
   GPIO_InitTypeDef GPIO_InitStructure; //Структура содержащая настройки порта
   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); //Включаем тактирование порта D
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12| GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15; //Выбераем нужные вывод
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //Включаем режим выхода
   GPIO_Init(GPIOD, &GPIO_InitStructure); //вызов функции инициализации


   usart_init(); //Инициализируем UART
   //Настраиваем прерывания по приему
   __enable_irq(); //Глобальное включение прерывания
   NVIC_EnableIRQ(USART2_IRQn); //Включаем прерывания от UART
   NVIC_SetPriority(USART2_IRQn, 0); //Прерывание от UART, приоритет 0, самый высокий
   USART2->CR1 |= USART_CR1_RXNEIE; //Прерывание по приему

    while(1)
    {

    }
}


void USART2_IRQHandler (void)
{
      char uart_data;
      if (USART2->SR & USART_SR_RXNE) //Проверяем, прилош ли чтонибудь в UART
      {
      USART2->DR = USART2->DR; //Echo по приему, символ отправленный в консоль вернется
      uart_data=USART2->DR; //Считываем то что пришло в переменную...
      uart2_rx_buf[uart2_rx_bit]=USART2->DR; //Помещаем принятый байт в буфер.
       uart2_rx_bit++; //Наращиваем счётчик байтов буфера.

       if(uart_data=='\r') //Если пришло сообщение о нажатии Enter...
       {
          GPIO_ResetBits(GPIOD, GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //Сбрасываем все пины в «0»
          if(strcmp(uart2_rx_buf,"led0\r")==0) //Если пришла команда "led0"
          {
             GPIO_SetBits(GPIOD, GPIO_Pin_12); //Подаем «1» на PD12
          }
          else if(strcmp(uart2_rx_buf,"led1\r")==0) //Если пришла команда "led1"
          {
             GPIO_SetBits(GPIOD, GPIO_Pin_13); //Подаем «1» на PD13
          }
          else if(strcmp(uart2_rx_buf,"led2\r")==0) //Если пришла команда "led2"
          {
             GPIO_SetBits(GPIOD, GPIO_Pin_14); //Подаем «1» на PD14
          }
          else if(strcmp(uart2_rx_buf,"led3\r")==0) //Если пришла команда "led3"
          {
             GPIO_SetBits(GPIOD, GPIO_Pin_15); //Подаем «1» на PD15
          }
          
          else
          {
             send_str("\n"); //Переходим на новую строку
             send_str("String: ");
             send_str(uart2_rx_buf); //Отправляем ее обратно в консоль
          }

         memset(uart2_rx_buf, 0, sizeof(uart2_rx_buf)); //Очищаем буфер
         uart2_rx_bit=0; //Сбрасываем счетчик
         send_str("\n");
      }
      }
}


faddistr
Сообщения: 9

Сообщение faddistr » 27 сен 2014, 12:51

Чтобы перевести число из строки в число - надо отнять 0x30(цифры имеют аскии коды 0х30 - 0х39). Если число двухзначное XY, то bin=(X-0x30)*10+(Y-0x30). Аналогично для произвольной разрядности... Но в теории ничего не должно мешать сделать #include <stdlib.h> и воспользоваться стандартной функцией atoi

Rogers
Сообщения: 13
Откуда: МО, Климовск

Сообщение Rogers » 29 сен 2014, 14:44

Добавляю посреди кода например в main или в начале обработчика в конце:

Код: Выделить всё

int n; n =atoi(uart2_rx_buf); send_str(uart2_rx_buf);

ничего не срабатывает и в watch не отслеживается.
Если добавить во внутрь while(1). то после перезапуска n с char станет int, но просмотреть значение не удается.
Также был добавлен код для atoi()(со стандартным atoi в stdlib.h программа не реагирует):

Код: Выделить всё

int atoi(char* s)
{
    int n = 0;
    while( *s >= '0' && *s <= '9' ) {
        n *= 10;
        n += *s++;
        n -= '0';
    }
    return n;
}

faddistr
Сообщения: 9

Сообщение faddistr » 02 окт 2014, 09:45

Вроде бы должно работать, разве что int это знаковый тип, а у вас знак не учтен(иногда это критично). А по поводу вотча-есть в кейле такая бага, попробуйте обновить кейл и проверьте, что оптимизация отключена(оптимизатор может выбросить значение). Так-же все должно работать через просмотр памяти - для чего закиньте в качестве адреса &n(первые четыре будут ваше число в хексе, в little-endian).

Rogers
Сообщения: 13
Откуда: МО, Климовск

Сообщение Rogers » 16 окт 2014, 15:03

Проблема решена написанием собственного atoi т.к. штатный atoi не работает.

Вернуться в «Микроконтроллеры и ПЛИС»



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 0 гостей