User_1

Отправка строки в UART в stm32f030

63 сообщения в этой теме

Yurkin2015    317
23 минуты назад, snn_krs сказал:

Если довавить еще одну букву,

 

23 минуты назад, snn_krs сказал:

Чтение с 7-го байта вызовет ошибку.

Ну, вот, договорились до ручки! То есть, получается в слове "Hello" программа букву 'H' может прочитать, а следующую 'e' уже не может, потому что эта 'e' расположена по некратному адресу? :)

Процессор 32-битный, и все его регистры тоже 32-битные. Процессор читает из ППЗУ сразу 4 байта "Hell" в регистр, а потом уже начинает суетиться и разбивать прочитанное значение на байты и пользовать их по-байтно. Но эта внутренняя кухня уже не видна так очевидно.

А компилятор сам подровняет нужное число нулей в конце строки, чтобы следующее значение в ППЗУ начиналось с кратного 4-м адреса. Вон, не зря же в примере выше в конце "Hello World!" стоят аж 4 байта нулей, а не один только байт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Чем это SPL лучше HAL? и при чем тут Keil.

5 минут назад, Yurkin2015 сказал:

Процессор 32-битный, и все его регистры тоже 32-битные. Процессор читает из ППЗУ сразу 4 байта "Hell" в регистр, а потом уже начинает суетиться и разбивать прочитанное значение на байты и пользовать их по-байтно. Но эта внутренняя кухня уже не видна так очевидно.

Не пишите глупости

Товарищи при доступе к байтам ничего выравнивать не нужно, это ваши фантазии.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
User_1    4
44 минуты назад, Yurkin2015 сказал:

А компилятор сам подровняет нужное число нулей в конце строки

Вот содержимое памяти когда передаю строку (Send_to_UART("Hello World!");):2018-09-21_21-17-48.png.7c0a3000b2a87a09293ca46f3e44703f.png

А вот содержимое памяти, когда передаю в функцию массив

(char hello[] = {"Hello World!"};

Send_to_UART(hello);):

2018-09-21_21-15-26.png.6c3bd37559a83ee5c8dde3f9866a4b52.png

Верхний вариант не работает, нижний - работает

Изменено пользователем User_1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
artos5    290

Странные эти ф0...

7 минут назад, User_1 сказал:

Верхний вариант не работает,

Дописывать программно ноли , если сумма символов не делится на 4.

Вот примерно так:

if(Chr%4!=0)

{ for()...}

И т.д. 

Пишу с телефона , поэтому неудобно полностью написать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
UTSource

Найдите миллионы труднодоступных

электронных компонентов

12 часа назад, User_1 сказал:

Почему-то этот код работает: 

Проблема в использовании указателя в сыром виде (*string). В этом случае читается всё что начинается с адреса string, это может быть один байт - если он старший, и все 4 байта - если он окажется младшим. Вместо этого нужно читать явно: while( string[0] ),   data = string[0].

Второе: указатель принимает адрес константы, + этот адрес находится в параметре функции - операции c подобными переменными дурной тон. Необходимо создать новый указатель в самой функции, и менять его как хочется. Функция не должна менять внешний указатель в своём параметре. В противном случае повторное использование функции может дать весёлый результат.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
12 минуты назад, AVI-crak Home сказал:

В противном случае повторное использование функции может дать весёлый результат.

это разве что выдавать два раза одну и ту же строку подряд с максимальной оптимизацией. А так по идее ничего страшного и нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    555
	char data = 0;
	while(*string)
	{
		while(!(USART_GetFlagStatus(USART1, USART_FLAG_TXE)));
		data = *string;
		USART1->TDR = data;
		string++;
	}

Зачем тут ещё одна переменная (data) ? 
Достаточно :

	while(*string)
	{
		while(!(USART_GetFlagStatus(USART1, USART_FLAG_TXE)));
		USART1->TDR = *string++;
	}

И проблема, вероятнее всего, именно в этом.
Компилятор под переменную выделяет целый регистр, просто работает потом с отдельной его частью (байтом). И чтение целого регистра по невыровненному адресу (через указатель) вызывает системное исключение.
Хотя, могу ошибаться. Проверить свои мысли нет возможности.
 

8 часов назад, MasterElectric сказал:

А так по идее ничего страшного и нет.

Речь, скорее всего, шла о правиле хорошего тона.
Если функция не модифицирует данные по указателю-аргументу, он должен быть объявлен с квалификатором "const". Это нужно изначально "зарубать на носу". Ибо в дальнейшем могут повалиться ошибки при, например, попытке передачи в функцию указателя на константу. А человек, пишущий программу, будет в недоумении - с какого хера он меня материт за то, что я объявил объект константным и передаю его указатель в функцию, которая не должна менять мои данные, а просто куда-нибудь их выводить ...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
User_0    0
10 hours ago, MasterElectric said:

Все нормально работает

Можете показать как вы написали?

(это я же, только из дома)

У меня тоже всё работает, если использовать хал. Но хотелось бы сделать всё используя SPL

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    555
53 минуты назад, User_0 сказал:

У меня тоже всё работает, если использовать хал.

Дак подсмотрите как там сделано и сравните :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

CMSIS

// передаем 1 байт
void USART_RxReset(void)
{
  USART_Rx_Cnt = 0;
  USART1->CR1 |= USART_CR1_RE;
}

void USART_Transmit(USART_TypeDef *tUSART, uint8_t Data)
{
  while(!(tUSART->ISR & USART_ISR_TC));
  tUSART->TDR = Data;
}

// передаем буфер
void USART_TransmitBuff(USART_TypeDef *tUSART, uint8_t *tData, uint32_t tCnt)
{
  while(tCnt--) USART_Transmit(tUSART, *tData++);
  USART_Status &= ~(USART_STATUS_RXCMPL | USART_STATUS_RXERR);
  USART_RxReset();
}

void USART_TransmitString(USART_TypeDef *tUSART, const char *tData)
{
  while(*tData) USART_Transmit(tUSART, *tData++);
  USART_Status &= ~(USART_STATUS_RXCMPL | USART_STATUS_RXERR);
  USART_RxReset();
}

//*******************************************************************************
  USART_TxBuff[0] = 0;
  USART_TxBuff[1] = 1;
  USART_TxBuff[2] = 2;
  USART_TxBuff[3] = 3;
  USART_TxBuff[4] = 4;
  USART_TxBuff[5] = 5;

  USART_TransmitBuff(USART1, USART_TxBuff, 6);
  USART_TransmitString(USART1, "123456 ");
  USART_TransmitString(USART1, "123456789 ");
  USART_TransmitString(USART1, "12345 ");
  USART_TransmitString(USART1, "123 ");
  USART_TransmitString(USART1, "12 ");

без прерываний и ДМА, тупо в лоб. Позже сделаю нормально не работал особо с F0.
void Usart1_Init(void)
{
  RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
  RCC->APB2ENR |= RCC_APB2ENR_USART1EN;

  TGPIO::SetMode(PA2, (gpAlternateMode | gpSpeedHigh | gpAF1));
  TGPIO::SetMode(PA3, (gpAlternateMode | gpSpeedHigh | gpAF1));

  USART1->BRR =(APBCLK + BAUDRATE/2)/BAUDRATE;
  USART1->RTOR= 100;
  USART1->CR1 |= USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE | USART_CR1_RTOIE;
  USART1->CR2 |= USART_CR2_RTOEN;

  USART1->CR1 |= USART_CR1_UE;

  USART_Status = 0;

  NVIC_SetPriority(USART1_IRQn, 0);
  NVIC_EnableIRQ(USART1_IRQn);
}
/* USART */
uint8_t    USART_RxBuff[40];
uint8_t    USART_TxBuff[40];
uint8_t    USART_Rx_Cnt;
uint8_t    USART_Tx_Cnt;
uint32_t   USART_Status;

#define    USART_STATUS_RXCMPL           (1 << 0)
#define    USART_STATUS_RXERR            (1 << 1)
#define    USART_STATUS_TXCMPL           (1 << 2)

а еще прием:

// прерывание от USART1
void USART1_IRQHandler(void)
{
  if(USART1->ISR & USART_ISR_RXNE)
  {// пришли данные по юарту
   if(USART_Rx_Cnt < sizeof(USART_RxBuff))
   {
	USART_RxBuff[USART_Rx_Cnt++] = USART1->RDR;
   }
   else
   {// переполнение буфера

   }
  }

  if(USART1->ISR & USART_ISR_RTOF)
  {
   USART1->CR1 &= ~USART_CR1_RE;
   USART_Status |= USART_STATUS_RXCMPL;
   USART1->ICR|=USART_ICR_RTOCF;
  }
}

потом  в общем цикле нужно опрашивать флаги юарта:

  while(1)
  {
   /* СОБЫТИЯ USART */
   if(USART_Status & USART_STATUS_RXCMPL)
   {// приняли пакет
    ...
    USART_Status &= ~USART_STATUS_RXCMPL;
   }


  }     
     

 

Изменено пользователем MasterElectric

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
User_0    0

Интересно

Передача по сути точно так же реализована. В понедельник тупо скопирую и проверю. Спасибо)

 

Кстати, а почему все пишут отдельную функцию для передачи одного байта и из функции для передачи строки для каждого байта вызывают эту первую функцию? Это же медленнее

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
artos5    290
6 часов назад, User_0 сказал:

Кстати, а почему все пишут отдельную функцию для передачи одного байта и из функции для передачи строки

Так удобнее и меньше занимает ресурсов , если эта функция часто вызывается .

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Это просто для опробования в новом камне, а так USART работает исключительно с DMA как на прием, так и на передачу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
artos5    290

Вот мой пример приема символов:

https://drive.google.com/file/d/14cOYggEWX-_MqzywETzumDk3S6Y3qVBe/view?usp=drivesdk

Есть пример где через калбэк функцию принимаются символы и загружаются в массив . Но там особого отличия нет.

Только что, artos5 сказал:

USART работает исключительно с DMA как на прием, так и на передачу.

На передачу оправдано , а на прием - не понятно как это использовать, там передается либо половина буфера либо целый , а у меня всегда размер буфера разный . И на передачу часто камень вешается , поэтому я использую через прерывания . 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Там где новая версия USART есть Receiver timeout, когда произошел останавливаем прием. ДМА настраиваем на макс. размер буфера если достигли все это переполнение. Там где нет  использую IDLE но там фиксированная длина в 1.5 символа иногда это слишком мало. В тех что постарше (F4) хочу попробовать сделать прием на 2 каналах ДМА. второй канал для таймера. Но зато все работает в фоне.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
User_1    4

В общем получить ассемблерный листинг прямо из CoIDE мне не удалось, однако, сравнивая получаемые в результате компиляции бинарники (приложил) увидел кое-какие отличия. Я сравнивал варианты когда в функцию передаю массив (вариант 1) и строку (вариант 2). Единственным существенным отличием оказалась команда по адресу 0х724. В варианте с массивом там была команда C4 0D 00 08, а в варианте со строкой - D1 0D 00 08. Что это за команды и что они делают я не знаю, но если в мк залить прошивку с передачей в функцию строки, а потом с помощью ST-Link Utility изменить один этот байт - мк оживает, отладка работает нормально, "Hello World!" передаётся. Выходит, проблема в компиляторе (у меня версия 5.4 2016q2) или в самом кококсе (у меня версия 1.7.8). Возможно, само ядро микроконтроллера некорректно обрабатывает эту команду.

Проект тоже приложил в архиве, если кому интересно - попробуйте. Вдруг у вас другая версия CoIDE при той же версии компилятора или наоборот.

 

Файлы в приложении:

В архиве сам проект

Array.bin - файл, полученный при компиляции версии, где в функцию передаётся массив

String.bin - файл, полученный при компиляции версии, где в функцию передаётся строка (непосредственно то, что выдаёт компилятор)

String_ok.bin - файл String.bin, но в нём я вручную заменил команду D1 0D 00 08 на C4 0D 00 08.

Каждый из этих файлов можно залить в мк и увидеть, что первый и третий работают, второй - нет. Так же легко увидеть, что второй и третий отличаются всего на один байт (как раз та команда). Юарт здесь настроен на скорость 19200

Напомню, проект для камня STM32F030F4P6

String_ok.bin

Array.bin

String.bin

STM32F030_USART.rar

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Oxford    24

в KEIL программировать надо и не надеяться на глючный GCC.

Изменено пользователем Oxford

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
User_1    4
21 минуту назад, Oxford сказал:

в KEIL программировать надо

Keil стоит неоправданно дорого, а пользоваться пиратским софтом совесть не позволяет

давайте не будем разводить дискуссии на тему какая среда лучше

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
User_1    4
2 минуты назад, Oxford сказал:

Ключ для F0/L0 бесплатно

Это первый коммерческий проект на F0, в основном использую F105 (там два модуля CAN) и присматриваюсь к F40х.

32кб хватит чтобы попробовать среду, для серьёзных проектов этого мало

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Oxford    24

Ну KEIL деньги берет не просто так. Если нужен ключ для KEIL, могу активировать до проф версии.

Изменено пользователем Oxford

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ваша публикация должна быть проверена модератором

Гость
Вы не авторизованы. Если у вас есть аккаунт, пожалуйста, войдите.
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Восстановить форматирование

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

Загрузка...

  • Похожие публикации

    • Гость Andrey-Docent
      Автор: Гость Andrey-Docent
      Всем привет! Планируется сделать на базе arduino устройство, ведущее обмен данными с переферийным устройством по интерфейсу rs-232 и также необходимо контролировать работу arduino с помощью компьютера тоже посредством интерфейса rs-232. Но у arduino только один такой порт. Первая мысль в связи с этим - сделать ещё один порт и вывести линии RX и TX на другие (например цифровые) ножки порта. Можно ли как-то это сделать? Нет ли готовых библиотек для этого (на данный момент не нашёл таковых в интернете)? Может есть ещё какой-нибудь обходной путь? Заранее спасибо.
    • Гость Максим
      Автор: Гость Максим
      Всем светлым и умным головам привет!

      Никак не могу найти информацию о данном прерывании TIM1_BRK_UP_TRG_COM.
      Вопрос 1: Что это за стек или система прерываний? 
      Вопрос 2: Когда будет вызываться обработчик прерывания TIM1_BRK_UP_TRG_COM_IRQHandler, если также есть обработчик прерывания TIM1_CC_IRQHandler?
      Вопрос 3: период переполнения таймера равен 100 мкс. Сколько раз будет вызываться обработчик прерывания TIM1_BRK_UP_TRG_COM_IRQHandler до обработчика прерывания TIM1_CC_IRQHandler? По логике вещей, предполагаю, что 100 раз?
      Заранее благодарен!

      Всем радости))
    • Автор: User_1
      Доброго времени суток!
      Вкратце: нужно после того, как я записал байт данных в SPI1->DR, отменить передачу этого байта и вместо него отправить 0х00
      Подробно: Смысл вот в чём: некий контроллер, с которым я пытаюсь наладить общение по SPI, запрашивает произвольный участок массива байт и считывает их сплошным потоком. Ну примерно как считывается микросхема EEPROM: задаёшь начальный адрес, а потом просто шлёшь сплошные 0xFF, а она сама инкрементирует адрес и прямо непрерывным потоком байт выдаёт содержимое памяти. Только тут в роли этой микросхемы мой stm32f030 и мне нужно следующий байт отправлять в SPI1->DR сразу после отправки предыдущего. Но когда поток заканчивается (а он каждый раз разной длины и длина эта заранее неизвестна), один байт остаётся не переданным и отправится первым при следующем запросе. А мне нужно, чтобы первым байтом всегда отправлялся 0х00
      Пином (ну то есть битом) NSS управляю программно, его выставление в единичку и снова в ноль, очевидно, не помогает вообще никак. Пока решил проблему так: деинициализирую модуль SPI и выключаю его тактирование, затем включаю тактирование и снова инициализирую. Работает, скорости хватает. Но должно же быть менее костыльное решение?)
      Может кто сталкивался с такой проблемой?
      Курение даташита, reference manual и результатов поиска в гугле, не особо помогло.
    • Автор: LiVit
      Добрейшего всем времени суток!
      Случилось недавно моему заказчику захотеть защитить прошивку от считывания (да, я знаю, люди эту защиту сковыривают на раз, но это уже не моя беда). А так как делать это вручную, при прошивке каждого проца, довольно геморройно, было решено добавить в код "самозащиту".
      Почитав мануал на проц, погуглив, почитав комментарии в stm32F0xx_flash.h, я написал следующий код:
          #include "stm32F0xx_flash.h"     if (RESET == FLASH_OB_GetRDP())        //checking protection status     {         FLASH_OB_Unlock();    //unblock the Option Byte         if (FLASH_COMPLETE == FLASH_OB_RDPConfig(OB_RDP_Level_1))     FLASH_OB_Launch();         FLASH_OB_Lock();     } Казалось бы, всё сделано так, как рекомендовано. Тем не менее, этот код не работает.
      Гугль показал, что данная тема волнует не только меня, но и других камрадов. 
      В общем, правильное решение выглядит так:
          #include "stm32F0xx_flash.h"         if (RESET == FLASH_OB_GetRDP())        //checking protection status     {         FLASH_Unlock();    //unblock the FLASH (!!)         FLASH_OB_Unlock();    //unblock the Option Byte         if (FLASH_COMPLETE == FLASH_OB_RDPConfig(OB_RDP_Level_1))     FLASH_OB_Launch();         FLASH_OB_Lock();         FLASH_Lock();     } Обратите внимание, - перед тем, как разблокировать Option Byte, необходимо разблокировать саму флэшь.
    • Автор: User_1
      Всем доброго времени суток!
      Кто-нибудь может поделиться рабочим примером инициализации I2C в STM32F030? Ну или может увидите в моём коде ошибку
      RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); // Включаем тактирование RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); I2C_InitTypeDef I2C_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3; // Speed 50 MHz GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // Альтернативная функция GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // Без подтяжки GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; // Открытый сток GPIO_Init(GPIOA, &GPIO_InitStructure); I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; // Режим работы (I2C) I2C_InitStructure.I2C_OwnAddress1 = 0x11; // Адрес (не важен, если устройство - мастер) I2C_InitStructure.I2C_Timing = 0x00300619; // Значение для записи в регистр I2C_TIMINGR I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_Cmd(I2C1, ENABLE); I2C_Init(I2C1, &I2C_InitStructure); Полдня уже вожусь, никак не заводится. Компилится без ошибок, светодиод мигает (ну в основном цикле написана простая светодиодная мигалка и раз в секунду - отправка сообщения в I2C), но смотрю логическим анализатором - на ножках тишина (ну в смысле единичка всегда, они же подтянуты резисторами к плюсу)
      I2C_Timing рассчитывается калькулятором от ST (I2C Timing Configuration) на основе частоты тактирования модуля I2C,  желаемой скорости шины и ещё пары параметров, калькулятор прикрепил к сообщению
      I2C_Timing_Configuration_V1.0.1.xls
  • Сообщения

    • Ну, вот и молодец! Иной раз передовые технологии не такие уж технологичные. А вот здравый смысл никто не отменял. Кстати, привод тоже купи - полезная штука (особенно САТА)
    • Вопрос в том что резисторы в затворы при параллельном соединении полевиков нужны в любом случае, резисторы нужны низкоомные, но вот если есть эмиттерный повторитель расчитаный на импульсный зарядный ток емкостей двух затворов, если ставить резисторы выравнивающие неравномерность емкостей затворов двух полевых транзисторов, то их нужно ставить как можно низкоомные, так как мне нету смысла ограничивать импульсный зарядный ток емкостей, так как эмиттерный повторитель тянет без проблем, но вот в каких пределах поставить эти резисторы в затворы после эмиттерного повторителя при параллельном соединении полевиков, чтобы и не сильно уменьшать этот зарядный ток(следовательно увеличивать время переключения полевиков, так как мне нужны как можно круче фронты), ну и чтобы эти резисторы компенсировали неравномерность емкостей затворов.
    • Это с какой такой радости они коротят мост? А дроссель там для кого? Читай, что такое корректор коэффициента мощности и как он работает.
    • Стоп. Вы однозначно заявили, что обмотки 17В сверху, значит трансформатор под перемотку.   Во-первых, говорите только за себя. остальные 90% форумчан сами за себя решать умеют. Во-вторых, вы это, опять же, ничем не обосновываете. Так, лапнули лишь бы было.
    • При разборке БП обнаружил, что транзисторы Q603 Q604 хорошо пыхнули, лишившись своих корпусов.
      Скорее всего эти транзисторы управляют ключами Q601 Q602, которые по сути могут коротить диодный мост. Но зачем так жестоко ?? Может кто пояснить ? Схему прицепил.
    • Запустил свою первую заводскую плату УМ!  Действительно, скучный усилитель - выставил ток, подобрал коррекцию, и все .  В коррекции с большим запасом получились те же 5.6пф, что и на макете.  
    • Так со стабилизатором/бесперебойником скачки не устранятся.  Если только апс не онлайновый