Jump to content

    

теряются символы UART STM32F030

Привет!

 

Использую UART как консоль - вывожу одной строкой нужные мне данные с интервалом в секунду. Проблема в том, что ИНОГДА теряются символы. Выглядит это примерно так:

 

1556 mV | rise= | l | panel= | panel=4 | ltsw= 0 14 | pan curren0 | bat= 10 | bat= 1A | D= 10nt= -161 nt= -161 chg curre-165 mA | -165 mA | urrent= = 0 |

= 0 |

556 mV | rise64 | ltsw=64 | ltsw=2 pan curre pan curre= 28 |00 | bat= 00 | bat= mA | D= 112195 mV | chg curr current= current=8 mA | pev6 mV | ri6 mV | ri | ref= 155se= 0 |

307 | lts307 | lts w= 0 | panel= 144 mA | D=4 mA | D=rrent= -2V | chg cuV | chg cu= 12195 mev currentev current67 mA | p556 mV | r556 mV | r | ref= 1ise= 0 |

| light=anel= 2anel= 2sw= 0 | p-24 mA | D-24 mA | Drrent= = 100 | bat= 12200 -165 mA | -165 mA | urrent= mA | ref=mA | ref=nt= -167 |

|

556 mV | rise= 0 | light= 302 | ltsw= 0 |current= current= 14 | pan bat= 1220 bat= 1220 D= 100 | -165 mA current=5 mA | ref5 mA | refent= -16= 1556 mV | rise= 0 |

| ltsw= 0 | ltsw= 0 308 n currentn current 28 | pa= -24 mA | D= 100 hg currenhg curren195 mV | crrent= -rrent= -mA | pev cumV | rise=mV | rise=ef= 1556 0 |

| light= 28 28 | 28 | 0 | panel=mA | D= 10mA | D= 10t= -33 chg curre chg curre2189 mV |current= current= mA | pev -168 mA | ref= 1556 mV | rise= 0 |

light= 2 l= 28 l= 28 = 0 | pane| pan current= -3 12189 mV 12189 mV 100 | bat=66 mA | perent= -1 | ref= 15 | ref= 15 -164 mA56 mV | rise= 0 |

light= 2 l= 28 = 0 | pane| pan current= -24 12195 mV 12195 mV100 | bat= | chg current= -168 mA | pev current= -166 mA | ref= 1556 mV | rise= 0 |

| lig 14 | pan 14 | pan ltsw= 0 | panel= | D= 100 | D= 100 -26 mA hg currenthg current95 mV | c= -168 mA | pev cuef= 1556 mef= 1556 m68 mA | rV | rise= 0 |

| light= 269 | ltsw= 0 | panel= 28 | pan current= -32 mA | D= 100 | bat= 12189 mV | chg current= -162 mA | pev current= -168 mA | ref= 1556 mV | rise= 0 |

| light= 268 | ltsw= 0 | panel= 0 | pan current= -28 mA | D= 100 | bat= 12184 mV | chg current= -165 mA | pev current= -162 mA | ref= 1556 mV | rise= 0 |

| light= 269 | ltsw= 0 | panel= 28 | pan current= -30 mA | D= 100 | bat= 12184 mV | chg current= -165 mA | pev current= -165 mA | ref= 1556 mV | rise= 0 |

| light= 311 | ltsw= 0 | panel= 0 | pan current= -25 mA | D= 100 | bat= 12195 mV | chg current= -166 mA | pev current= -165 mA | ref= 1556 mV | rise= 0 |

| light= 310 | ltsw= 0 | panel= 14 | pan current= -25 mA | D= 100 | bat= 12184 mV | chg current= -157 mA | pev current= -166 mA | ref= 1556 mV | rise= 0 |

| light= 308 | ltsw= 0 | panel= 28 | pan current= -30 mA | D= 100 | bat= 12189 mV | chg current= -162 mA | pev current= -157 mA | ref= 1556 mV | rise= 0 |

 

Сначала видно бардак поскольку часть символов выпала, в последних 6ти строках все ок. Причем я специально скопировал тот момент когда проблема пропала, при том что девайс никто не трогал и внешние условия не менялись. Вывод осуществляется одной строкой в цикле:

 

printf("| light=%5d | ltsw=%2d | panel=%6d | pan current=%6d mA | D=%4d | bat=%6d mV | chg current=%6d mA | pev current=%6d mA | ref=%5d mV | rise=%2d |\n", light, ltsw, panel, paneli, d, bat, bati, bati_prev, ref, rise);

 

Инициализация порта с сайта кейла:

 

#include <stm32f0xx.h>

 

/*----------------------------------------------------------------------------

Initialize UART pins, Baud-rate

*----------------------------------------------------------------------------*/

void init_serial (void) {

int i;

 

/* Configure UART2 for 9600 baud */

RCC->AHBENR |= RCC_AHBENR_GPIOAEN; /* Enable GPIOA clock */

GPIOA->MODER |= GPIO_MODER_MODER9_1; // PA9 as alternative GP Output (USART1_TX)

GPIOA->MODER |= GPIO_MODER_MODER10_1; // PA10 as AF

GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9; //high speed (current?) output

GPIOA->AFR[1] |= 0x110; // PA9, PA10 Alternative function 1 (USART1) enable

RCC->APB2ENR |= RCC_APB2ENR_USART1EN;/* Enable USART1 clock */

USART1->BRR = 0x0341; /* Configure 9600 baud, */

for (i = 0; i < 0x1000; i++) __NOP();/* avoid unwanted output */

USART1->CR1 |= (USART_CR1_UE | USART_CR1_RE | USART_CR1_TE); // Enable USART, Receive and Transmit

}

 

 

/*----------------------------------------------------------------------------

Write character to Serial Port

*----------------------------------------------------------------------------*/

int sendchar (int c) {

 

while(!(USART1->ISR & USART_ISR_TXE));

USART1->TDR = (c & 0x1FF);

return ©;

}

 

 

/*----------------------------------------------------------------------------

Read character from Serial Port (blocking read)

*----------------------------------------------------------------------------*/

int getkey (void) {

 

while (!(USART1->ISR & USART_ISR_RXNE));

return (USART1->RDR);

}

 

Сначала грешил на пролификовский адаптер, подкючил к машине с аппаратным компортом - таже фигня.

Причем проблема проявляется на 2х разных контроллерах (STM32F030F4P6 b STM32F030C8T6) в разных устройствах с разной фирмварью но одинаковым кодом инициализации порта и и вывода (все приведено выше). Во втором устройстве параметров вдвое меньше в printf, соответственно отображаемая строка короче но проблема абсолютно та же. Компы тоже разные. Пробовал с ноутом работающим от батареи и устройством питающимся от другой батареи - эффект аналогичный.

 

Обычно вывод нормализуется через час-два работы устройства (заметил случайно раза 3, уже не совпадение) но не всегда и сколько-нибудь заметного нагрева нигде нет. Форма сигнала ТХ выглядит нормально как на ноге контроллера так и на ноге ком порта (после преобразователя уровня) и одинакова при корректном выводе и "побитом".

 

Код инициализации вроде бы понятен но непонятно зачем 0x1FF в строке USART1->TDR = (c & 0x1FF);

Пробовал USART1->TDR = c; разницы никакой не обнаружил. Объясните пожалуйста зачем это нужно.

 

Ну и главный вопрос - в чем может быть проблема с выводом.

Edited by greenhorn

Share this post


Link to post
Share on other sites

& 0x1FF нужно для того, чтобы гарантировать, что в уарт не записывается число длиннее 9 бит

Терять может если есть переход контроллера в режим STOP, хотя наверное у вас этого нет.

Может быть проблема в терминальной программе, попробуйте логировать в файл.

Многие параметры взяты "по умолчанию", регистры не настраивались, но вроде 8N1 должно быть нормально. Тем не менее, я все таки рекомендую пользоваться Standart Peripherial Library или CibeMX, а то проверять каждый бит настройки довольно утомительно.

Share this post


Link to post
Share on other sites

printf работает только в одном потоке? Из других потоков печатать не пытаетесь?

 

Может HSI не достаточно стабилен?

Share this post


Link to post
Share on other sites
printf работает только в одном потоке? Из других потоков печатать не пытаетесь?

 

В одном. Более того кроме этого единственного принтфа с UART ничего больше не работает. Опрашиваю в цикле ацп, входные PIO, вывожу результатя на печать. Больше в программе ничего нет. Прерываний и энергосберегающих режимов нет. Работаю от внутреннего RC, грешил на частоту, вывел на MCO и померял частотомером - 7.991 MHz

 

& 0x1FF нужно для того, чтобы гарантировать, что в уарт не записывается число длиннее 9 бит

Вот спасибо - всю голову сломал а до такого банального не додумался.

 

Терять может если есть переход контроллера в режим STOP, хотя наверное у вас этого нет.

Может быть проблема в терминальной программе, попробуйте логировать в файл.

 

Как написал выше - никаких стопов все очень тупо. А вот Bray's terminal это единственное что было неизменно во всех экспериментах, завтра буду пробовать, спасибо.

 

Многие параметры взяты "по умолчанию", регистры не настраивались, но вроде 8N1 должно быть нормально. Тем не менее, я все таки рекомендую пользоваться Standart Peripherial Library или CibeMX, а то проверять каждый бит настройки довольно утомительно.

 

Тут у меня огромная проблема с отсутствием (или немогу найти, или просто не понимаю) лоичной и последовательной документации по CMSIS и Standart Peripherial Library. По первому вообще больше по хидерам разбираюсь. Способ наверное традициооно программерский но как по мне -неправильный. В общем пока у меня с этим не сростается....

Share this post


Link to post
Share on other sites

Попробуйте вместо TXE, TC дожидаться и сбрасывать его незабыть, тогда будет более птонятнее.

Share this post


Link to post
Share on other sites

Все прекрасно работает по TXE как и описано в документации. От перехода к проверке TC тут ничего не изменится (и не должно).

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

USART1->BRR = UART1_CLOCK_FREQ / BAUDRATE;

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

 

P.S. и используйте, пожалуйста, кнопку rte-code-button.png на форме ввода сообщения для публикации исходников.

Share this post


Link to post
Share on other sites

не стал вникать в код из первого сообщения, но так понял, что контроллер шлёт данные, а программа на компе иногда не видит некоторых символов. Если контроллер работает только на передачу и со стороны компьютера никаких запросов нет, то для начала нужно определиться с неисправным звеном - МК или ПК. Самый простой способ - распаралеллить данные с МК на два компьютера с запущенной принимающей программой и сравнивать. Если пропуски будут совпадать на обоих компах, то проблема в МК, если вразнобой, то косяк на стороне ПК. Если выяснится, что дело в контроллере, то нужно будет оставить только функцию отправки данных, отключить все лишние прерывания и в бесконечном цикле гнать заранее известные данные на ПК. Если опять будут встречаться пропуски, то дело может быть в частоте кварца и если эти пропуски раз в час-два, то тут уместно будет применить контрольную сумму, если есть возможность изменить программу на компьютере. Для проверки плавания частоты можно всю плату погеть феном, одновременно наблюдая за отправляемыми данными.

 

Тут у меня огромная проблема с отсутствием (или немогу найти, или просто не понимаю) лоичной и последовательной документации по CMSIS и Standart Peripherial Library. По первому вообще больше по хидерам разбираюсь. Способ наверное традициооно программерский но как по мне -неправильный. В общем пока у меня с этим не сростается....

упорядоченое описание на русском языке функций CMSIS есть в приложении к этой книге http://www.twirpx.com/file/1136980/ В продаже она есть в терраэлектронике.

Share this post


Link to post
Share on other sites
проблема проявляется на 2х разных контроллерах (STM32F030F4P6 b STM32F030C8T6) в разных устройствах с разной фирмварью но одинаковым кодом инициализации порта и и вывода

С учётом этого, "магического прогрева", а также того, что в приведённом примере фразы не столько теряются, сколько повторяются, причина скорее всего несоблюдении требований разводки, блокировки, согласования уровней и т.п.

Share this post


Link to post
Share on other sites

А если выводить раз в две секунды?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this