User_1

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

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

User_1    4

Всем привет!

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


void Send_to_UART(char* string)
{
	char data = 0;
	while(*string)
	{
		while(!(USART_GetFlagStatus(USART1, USART_FLAG_TXE)));
		data = *string;
		USART1->TDR = data;
		string++;
	}
	while(!(USART_GetFlagStatus(USART1, USART_FLAG_TXE)));
	USART_SendData(USART1, 0x0D);
	while(!(USART_GetFlagStatus(USART1, USART_FLAG_TXE)));
	USART_SendData(USART1, 0x0A);
	while(!(USART_GetFlagStatus(USART1, USART_FLAG_TC)));
}

char hello[13] = {'H','e','l','l','o',' ','W','o','r','l','d','!'};

int main (void)
{
	Init_Clock();
	Init_USART1();
	Send_to_UART(hello);
	while(1);
}

А если написать вот так:


int main (void)
{
	Init_Clock();
	Init_USART1();
	Send_to_UART("Hello World!");
	while(1);
}

то не просто не работает - микроконтролер зависает даже до входа в main().

В Си ведь, насколько я понимаю, строка - это тот же массив символов

Объясните, пожалуйста, что я делаю не так?

Камень stm32f030, среда CooCox CoIDE

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


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

Допиши , string*+=0;

В функции sendtouart()

И ещё что за непонятный цикл while() в конце?

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


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

Допиши , string*+=0;

И ещё что за непонятный цикл while() в конце?

Не совсем понял: string*+=0 - Sintax error

Если написать *string+=0; - ничего не изменяется

while(); - просто бесконечный пустой цикл

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


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

Я щас скину рабочий пример , который работает на всех stm32

У меня пример для HAL
Но где то был и пример работы с регистрами напрямую , надо поискать.

void TFT_RS422_uart1(char *str) // display interface
{
	int x=0;
	str+=0;
  while(str[x])
  {
   x++;
  }	
if(x) HAL_UART_Transmit(&huart1,str,x,1000);
}

 

Вот нашел в закромах, работа с регистрами:

void Usart1_Send_symbol(uint8_t data) 
{
  while(!(USART1->SR & USART_SR_TC)); 
  USART1->DR = data; 
}


void Usart1_Send_String(char* str)
{
  uint8_t i=0;
  str+=0;
  while(str[i])
  {
    Usart1_Send_symbol(str[i]);
    i++;
  }
  Usart1_Send_symbol('\n');
  Usart1_Send_symbol('\r');
}

 

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


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

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

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

User_1    4
41 минуту назад, artos5 сказал:

Я щас скину рабочий пример

Переписал всё точно так же - и ничего не изменилось, если передать Send_to_UART(hello) - работает, а если Send_to_UART("hello") - зависает

Причём при компиляции ни ошибок ни предупреждений нет

str+=0 - это же просто прибавление нуля к указателю, какой смысл в этой операции?

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


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

Ну так str+=0 , дописывает 0 , где он проверяется в цикле , если этого не сделать будет зависать как раз.

У меня два данных примера работают и не зависают.

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


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

Ну так str+=0 , дописывает 0 , где он проверяется в цикле , если этого не сделать будет зависать как раз.

Не совсем так, я в отладчике ставлю breakpoint перед вызовом функции Send_to_UART(), сразу после инициализации - но даже инициализация не выполняется, микроконтроллер сразу попадает вот сюда:


.size Reset_Handler, .-Reset_Handler

/**
 * @brief  This is the code that gets called when the processor receives an
 *         unexpected interrupt.  This simply enters an infinite loop, preserving
 *         the system state for examination by a debugger.
 *
 * @param  None
 * @retval : None
*/
    .section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
  b Infinite_Loop
  .size Default_Handler, .-Default_Handler

(скопировал с описанием, чтобы нагляднее было)

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


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

Значит с инициализацией что то напутано  . Могу весь код скинуть , но он к f103

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


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

Могу весь код скинуть , но он к f103

От него мало пользы, тут инициализация немного иначе выполняется

Но, странно, если просто массив передавать - всё же нормально работает. Пробовал на разных скоростях - всё работает без нареканий

 

Ладно, чуть позже попробую бинарники сравнить, может там что увижу. Интересно посмотреть как хранятся в памяти массив и эта строка (должно же быть одинаково?) 

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

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


Ссылка на сообщение
Поделиться на других сайтах
IMXO    1 358
2 часа назад, User_1 сказал:

В Си ведь, насколько я понимаю, строка - это тот же массив символов

Объясните, пожалуйста, что я делаю не так?

ага.,

char hello[] = переменная, живет в ОЗУ

"Hello Word" = константа, живет ППЗУ

void Send_to_UART(char* string) = стучится в ОЗУ

или нет?

 

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


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

void Send_to_UART(char* string) = стучится в ОЗУ

Насколько я понимаю (поправьте, если ошибаюсь), в функцию же должен передаваться указатель на адрес первого элемента массива(строки). В стм32 единое адресное пространство, должно быть без разницы

 

Поэкспериментировал и пришёл к интересному результату:

Если вызываю функцию вот так:  Send_to_UART("ABCDEF"); - мк зависает, как и было раньше

Но если вызвать её вот так:  Send_to_UART("ABCDEFG"); - всё нормально, строка передаётся. То есть любая строка содержащая больше шести символов.

Сравнивал полученные при компиляции бинарники (прикрепил бинарники с 6- и 7-символьной строкой) - разница только в самой строке, других отличий нет

ABCDEF.bin

ABCDEFG.bin

 

UPD

Интересно, что если написать как раньше   Send_to_UART("Hello World!"); - не работает, а если без пробела - работает

(пробел же в хексе 0x20, не 0х00)

Аналогично "ABCDEFG" работает, а "ABC DEFG" - нет

UPD2

Посмотрел отладчиком на примере строки без пробела - string хранит вполне правильный адрес во флеше. Считываю содержимое камня с помощью ST-Link Utility - этот адрес как раз соответствует началу массива, который я передал в функцию

Изменено пользователем User_1
Исправил очепятку

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


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

void Send_to_UART(char* string) = стучится в ОЗУ

или нет?

Эта функция принимает строку , и не важно в ОЗУ она или ПЗУ . У меня и так и так работает и ничего не виснет .

Я как раз так и использую:

Send_to_UART("Test string");

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


Ссылка на сообщение
Поделиться на других сайтах
Yurkin2015    315
2 часа назад, IMXO сказал:

или нет?

У этих процессоров память ППЗУ и ОЗУ расположены в одном адресном пространстве. ППЗУ начинается с адреса 0х0000000, а ОЗУ начинается с адреса 0х20000000. Можно обращаться и читать любое место по любому адресу, без разницы.

Другое дело, как в программе добавлять 0 к строке, которая константа и прошита в ППЗУ навечно !?!

Да и не надо ничего добавлять, компилятор сам добавит 0 в конце строки-константы при компиляции и в ППЗУ эта строка будет уже с нулём на конце.

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


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

компилятор сам добавит 0 в конце строки-константы при компиляции

Так и есть, вот он, ноль в конце строки

2018-09-21_17-00-22.png

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


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

и все таки попробуйте для константы сделать как положено:

void Send_to_UART(const char* string)

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


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

и все таки попробуйте для константы сделать как положено:

void Send_to_UART(const char* string)

Это не для константы, const означает, что функция может читать данные, на которые указывает передаваемый ей указатель, но не может изменять их.

Пробовал, никакой разницы

Если в коде, с которым мк зависает, закомментировать вызов функции USART_Init() - мк не зависает (но юарт не работает, понятное дело). Инициализация простейшая, тут почти все значения по умолчанию:


	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	USART_InitTypeDef USART_InitStructure;

	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_Init(USART1, &USART_InitStructure);

	USART_Cmd(USART1, ENABLE);

 

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


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

Соберите в кубе проект и примените мой первый пример , уверен что все заведется сразу.

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


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

интересно так. В функцию должен быть передан указатель на строку. Когда он передается (hello  неявно передается как указатель, ибо он массив) то все работает. А когда передается строка (а это далеко не указатель, даже не явно) то все виснет. И это от чего то вызывает удивление. Кмк надо просто вспомнить базовый Си, и не важно где именно хранится константа. Важно как она обьявлена и как передается. Возможно надо просто для строк написать перезагружаемую функцию с аргументом другого типа и все будет работать.

прототип должен выглядеть так

void Send_to_UART(const char message[]);

и все будет нормуль

а уже в самой функции передачи можно явно переопределить аргумент как (uint8_t*)message

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

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

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


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

Совсем недавно этот вопрос обсуждался в ветке "STM для чайников". В М0 в ПЗУ хранятся только не упакованные данные.

Поэтому если строка с конечным 0 кратна 4-м все работает. Если не кратна то ошибка доступа к памяти.

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


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

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

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

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


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

А когда передается строка (а это далеко не указатель, даже не явно) то все виснет

Просто насколько я понимаю, строка в Си - это тот же массив символов и когда я вот так передаю строку - передаётся указатель на первый элемент этого массива. Для строк определённой длины ((4xN)+3) работает же. Если дело в кратности длины строки четырём байтам - звучит убедительно

 

Всё несколько иначе: он не успевает ничего передать просто потому что даже инициализацию не проходит. То есть я ставлю breakpoint на самом входе в main(), даже до инициализации, включаю отладку - и он зависает не дойдя до этой точки. И, повторюсь: если передать "Hello World!" - ничего не работает, а если "HelloWorld!" (то есть без пробела) - всё работает, а содержимое памяти мк отличается ровно на один байт - как раз этот пробел (но дело не именно в пробеле, если написать Hello_World! или HelloWWorld! - тоже не работает)

 

В хале всё работает, но код ровно вдвое больше)

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

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


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

А я думаю это как раз тот случай. "HelloWorld!" + 0 = 12 символов и работает. Добавите еще 4 символа и снова будет работать.

На картинке выше видно, если слово из 4-х букв например "Hell",  то они располагаются в обратном порядке с 3-го по 0-й байт. Если довавить еще одну букву, то она будет не в 4-м а в 7-м байте.

Чтение ПЗУ возможно с 0-го, 4-го и т.д. адресов. Чтение с 7-го байта вызовет ошибку.

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


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

Чтение ПЗУ возможно с 0-го, 4-го и т.д. адресов. Чтение с 7-го байта вызовет ошибку

Спасибо)

А есть способ это обойти средствами SPL или вручную?

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


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

А есть способ это обойти

Программно дописывать ноли например чтобы сумма символов делилась на 4

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


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

Охренеть.

Вот сейчас сотни человек юзающих KEIL и посылающих не просто helloworld-ы по UART, а что-то более осмысленное, да и зачастую генерящееся "на лету", смотрят на всё это с недоумением...

Граждане, завязывайте с кубами и кокосами.
Берите SPL, кейл и пишите. И всё будет работать. Я с кокоса, к примеру, спрыгнул после полугода использования, о чем не жалею.

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

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


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

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

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

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

  Разрешено не более 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
  • Сообщения

    • 1862 то, конечно другая, я про нее так до кучи вспомнил. А 1852 как то запустил без дросселя между землями. И ничего даже играла, потом поставил, как заметил.
    • В общем - неплохо. Шоттки не хотите ставить? В ТО-220 замечательно встанут. Да и в ТО-247. Места достаточно. Вместо этого уродства квадратного...
      R1 и R2, если уж так хотите ставить, можно увеличить раз в 5. Незачем полватта впустую переводить. По 47к будет нормально. У вас же там не меньше 50В, наверняка.
      А так они нужны только для ремонта или проверки - чтобы не подключить заряженные банки к платам. В рабочем состоянии усилитель и так разрядит конденсаторы при выключении от сети.
    • всё ещё в наличии: 15" AOC LM520A 15" (VGA, 12В 2,5А) Цена без бп 250р. В наличии 1шт.   17" Acer AL1716Fs 17" (VGA) Цена: 600р. В наличии 1шт.  Acer V173bm 17" (VGA) Цена: 600р В наличии 1шт. Samtron 73V 17" (VGA) Цена: 600р В наличии 1шт.   19" Samsung 940N 19" (VGA) Цена: 900р В наличии 1шт.  Viewsonic VA903B-3 19" (VGA)19" (VGA) Цена: 950р В наличии 1шт.   Внимание! Только  мониторы! Никаких шнуров и проводов в комплекте нет! 
    • @Falconist , что ж вы так сложно и неэкономно-то делали?! мостик же вобще не нужен - прямо на гирлянды сеть и подавать.
    • Так было бы о чём плакать ! А говорили : Не зря первая заповедь телемастера : " Клиент всегда врёт ! ". 
    • А что в нем лучше усовершенствовать? Просто я думал что с диодами шотки меньше потеря по питанию будет и они быстрее, поэтому и хотел их поставить   А конденсаторы большей емкости именно в цепи питания думал поменять. Это вообще никакого толку не даст?   А как на счет диодов и стабилитронов на самой плате усилителя, их тоже не имеет смысла менять? Или может транзисторы заменить на импортные?