Перейти к содержанию

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


User_1

Рекомендуемые сообщения

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" в регистр, а потом уже начинает суетиться и разбивать прочитанное значение на байты и пользовать их по-байтно. Но эта внутренняя кухня уже не видна так очевидно.

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

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

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

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
Ссылка на комментарий
Поделиться на другие сайты

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

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

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

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

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

if(Chr%4!=0)

{ for()...}

И т.д. 

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

Что может быть лучше в радиоэлектронике, чем программирование микроконтроллеров ?

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

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

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

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

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

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

12 минуты назад, AVI-crak Home сказал:

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

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

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

.

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

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

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

	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". Это нужно изначально "зарубать на носу". Ибо в дальнейшем могут повалиться ошибки при, например, попытке передачи в функцию указателя на константу. А человек, пишущий программу, будет в недоумении - с какого хера он меня материт за то, что я объявил объект константным и передаю его указатель в функцию, которая не должна менять мои данные, а просто куда-нибудь их выводить ...

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

10 hours ago, MasterElectric said:

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

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

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

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

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

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
Ссылка на комментарий
Поделиться на другие сайты

Интересно

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

 

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

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

6 часов назад, User_0 сказал:

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

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

Что может быть лучше в радиоэлектронике, чем программирование микроконтроллеров ?

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

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

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

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

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

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

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

Что может быть лучше в радиоэлектронике, чем программирование микроконтроллеров ?

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

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

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

В общем получить ассемблерный листинг прямо из 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

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

21 минуту назад, Oxford сказал:

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

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

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

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

2 минуты назад, Oxford сказал:

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

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

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

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

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

Изменено пользователем Oxford
Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

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

  Разрешено использовать не более 75 эмодзи.

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

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

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

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...