|
Не работает USART на STM32F100RB |
|
|
|
Sep 1 2015, 07:30
|
Частый гость
 
Группа: Участник
Сообщений: 110
Регистрация: 23-06-14
Пользователь №: 82 030

|
Здравствуйте, столкнулся с проблемой. Скажу сразу, я не первый день над её разрешением думаю, всё перепробовал и только сейчас решил обратиться сюда - может кто-нибудь и сталкивался. Дело в чём: хочу организовать обмен данными по COM-порту на STM32-VLDiscovery (в основе данной отладочной платы лежит STM32F100RB). Ну ок, прочитал необходимые разделы в Reference Manual, посмотрел примеры в интернете и решил делать. Сначала пошёл лёгким путём, решив отправлять один символ с микроконтроллера через небольшие промежутки времени (ну а потом организовал бы полноценный обмен). Использую keil uvision5. Написал программу с использованием библиотеки STDPeriph. Написал. Он присылает - но не те символы. Решил найти, в чём проблема, не нашёл. Решив, что во всём виновата библиотека  - полез в референс мануал с описанием регистров порта ввода/вывода и USART. Написал программу, без использования STDPeriph (её код ниже). Результат - тот же. Ну и решил искать, в чём проблема. Первая мысль - то, что baudrate не тот. Измерил частоту SYSCLK - 24 МГц, потом решил строго установить делители частоты для шин AHB (крепится к SYSCLK) и APB2 (на ней висят GPIOA(PA9 у данного порта - передатчик USART) и USART1). Ставил на эту шину и 24 МГц, и 6 МГц - результат тот же. Решил измерить выходной бодрейт с помощью осциллографа  - тут тоже всё нормально. Потом подумал, что во всём виновата терминальная программа на компе, поставил другую - не то, не в этом проблема. Далее решил, что переходник RS232-USB виноват. Проверил его дрова - всё норм, винда сама не ставила те, которые захотела, на всякий случай соединил RX с TX у переходника - работает на славу, принимает и передаёт. Также я ковырялся в коде, меняя стоп-биты, флаги, по которым идёт проверка, что регистр данных пуст - никакого результата. Стабильно выдаёт одни символы вместо других. Причём строго - вместо "a" выдаёт "O", вместо "2" выдаёт "6", вместо "b" выдаёт кавычку (0x27). В чём проблема - никак не пойму. Были мысли, что шум и т.д., надо организовывать проверку чётности, например. Но тут бодрейт - 9600, какие на этом бодрейте могут быть ошибки? Ещё не уверен, но может быть играет роль то, что отладочная плата питается от USB? но что-то не верится. Тогда сам микроконтроллер криво бы работал, а помигать светодиодом он всегда соглашался без проблем. Код приведён ниже. Код #include "stm32f10x.h" // Device header
void delay(long x); void initial(void);
int main(void) { uint8_t data; initial(); data = 0x62; while(1) { if(USART1->SR & USART_SR_TC) USART1->DR=data; delay(5000000); } }
void initial(void) { //AHB, APB2 clock configuration RCC->CFGR &=~RCC_CFGR_HPRE; RCC->CFGR |=RCC_CFGR_HPRE_DIV1; RCC->CFGR &=~RCC_CFGR_PPRE2; RCC->CFGR |=RCC_CFGR_PPRE2_DIV1; //APB2 clock value = 24MHz RCC->APB2ENR|=RCC_APB2ENR_IOPAEN; //GPIOA clock enable GPIOA->CRH &=~GPIO_CRH_MODE9; GPIOA->CRH |= GPIO_CRH_MODE9_1 | GPIO_CRH_MODE9_0; //Output mode, max speed 50 MHz GPIOA->CRH &= ~GPIO_CRH_CNF9; GPIOA->CRH |= GPIO_CRH_CNF9_1; //Alternate function output Push-pull RCC->APB2ENR|=RCC_APB2ENR_USART1EN; //USART1 clock enable USART1->CR1 |= USART_CR1_UE; //USART1 enable USART1->CR1 &= ~USART_CR1_M; //1 start bit, 8 bits of data USART1->CR2 &= ~USART_CR2_STOP; //1 stop bit USART1->CR1 &= ~USART_CR1_PCE; //Parity control disabled USART1->CR3 &= ~USART_CR3_RTSE; //RTS hardware flow control disabled USART1->CR3 &= ~USART_CR3_CTSE; //CTS hardware flow control disabled USART1->BRR=0x9C4; //0x9C4 - 9600 baudrate for 24 MHz of APB2 USART1->CR1 |= USART_CR1_TE; //Transmitter enable }
void delay(long x) { long i; for(i=0;i<x;i++); } Ещё момент - решил измерять побитно, что должно быть записано в микроконтроллер, что выдаёт осциллограф, подключённый к выводу передатчика USART и что получаем в программе терминала на компьютере. Символ "а": микроконтроллер: 01100001 осциллограф: 10000110 терминал: 01001111 Символ "2": микроконтроллер: 00110010 осциллограф: 01100100 терминал: 00110110 Символ "b": микроконтроллер: 01100010 осциллограф: 01000110 терминал: 00100111 Какой-то связи между вышеуказанными двоичными числами, я не вижу. И это меня вообще в тупик ставит.
|
|
|
|
|
Sep 1 2015, 08:04
|
Частый гость
 
Группа: Участник
Сообщений: 110
Регистрация: 23-06-14
Пользователь №: 82 030

|
Цитата(ViKo @ Sep 1 2015, 10:51)  Биты обычно по линии передаются, начиная с младшего. (У вас настройки не нашел. Пройдитесь по всем битам в управляющих регистрах.) Если так, то почти все нормально. Может, в настройках терминальной программы указано наоборот? Задайте 2 стопа. Надежнее искать начало и конец передачи будет, хотя бы визуально. Настройки порядка битов в регистрах не нашёл, но в терминальной программе есть функция "Inverse bits". Вместо 4F (01001111) стал выдавать F2 (11110010), а должен был выдавать символ "a". 2 стопа задавал, эффекта нет  P.S. "a" - это 01100001, на всякий случай
Сообщение отредактировал thamjell - Sep 1 2015, 08:05
|
|
|
|
|
Sep 1 2015, 08:21
|
Частый гость
 
Группа: Участник
Сообщений: 110
Регистрация: 23-06-14
Пользователь №: 82 030

|
Цитата(ViKo @ Sep 1 2015, 11:13)  Замечательно! И осциллограф вам ее показал. А терминальная программа обманула. Выводы? Ого. Странно, что я не заметил этого сразу. Я терминальным программам доверял, у меня их две поставлено. Ладно, буду сейчас с ними разбираться. Спасибо за помощь! Что в итоге получилось - ещё напишу)
Сообщение отредактировал thamjell - Sep 1 2015, 08:21
|
|
|
|
|
Sep 1 2015, 09:01
|
Частый гость
 
Группа: Участник
Сообщений: 110
Регистрация: 23-06-14
Пользователь №: 82 030

|
Цитата(Сергей Борщ @ Sep 1 2015, 11:48)  Больше всего эжто похоже на несовпадение скоростей. Я не вижу у вас в программе настройки тактирования на 24 МГц, от которых вы считаете коэффициент деления генератора битовой скорости. Я не знал, как определить данную частоту и сделал программу, которая считывает частоту с вывода MCO. Просмотрев регистры в режиме отладки, я увидел, что в качестве источника тактовой частоты используется PLL, проверил частоту с пина MCO при помощи осциллографа - показало 12 МГц, относительно к PLL он показывает частоту PLL, делённую на два (см. картинку), отсюда такие и выводы. Прикрепляю ещё одну картинку, это бит на экране осциллографа, его длительность - где-то около 105 мкс. Это даёт бодрейт 9524. Так что думаю, что тут ошибки нету. А вот с терминальными программами, вероятно есть ошибки, либо же в переходнике, хотя он успешно переправлял сам себе символы, да и с оборудованием нормально работал. Может быть стоит поработать с CTS и RTS? А то они отключены у меня.
Сообщение отредактировал thamjell - Sep 1 2015, 09:17
Эскизы прикрепленных изображений
|
|
|
|
|
Sep 1 2015, 10:41
|
Частый гость
 
Группа: Участник
Сообщений: 110
Регистрация: 23-06-14
Пользователь №: 82 030

|
Цитата(ViKo @ Sep 1 2015, 13:24)  Я пользуюсь программой HTerm. Настройки CTS, RTS не трогаю. Они не должны влиять, если сигналов нет. Вы сигналы смотрите до преобразователя уровней 3 В <-> 12 B? Какие сигналы после них? Возможно, я нашёл в чём проблема. Я сделал, чтобы микроконтроллер выдавал числа 0xFF. По идее - должны выделяться только стоповые биты (логический ноль). А терминал мне выдал 0х00. Записал в микроконтроллер 0x00 - терминал выдал 0xFF (этот случай сопровождаю фото с осциллографа). Такое ощущение, что логическая "1" для микроконтроллера - это логический "0" для терминала. Посмотрел по остальным символам - вроде как тоже это объясняет. Как это исправить можно?
Эскизы прикрепленных изображений
|
|
|
|
|
Sep 1 2015, 10:45
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(thamjell @ Sep 1 2015, 12:01)  Я не знал, как определить данную частоту и сделал программу, которая считывает частоту с вывода MCO. Просмотрев регистры в режиме отладки, я увидел, что в качестве источника тактовой частоты используется PLL, проверил частоту с пина MCO при помощи осциллографа - показало 12 МГц, относительно к PLL он показывает частоту PLL, делённую на два (см. картинку), отсюда такие и выводы. Эту частоту настроила предыдущая загруженная программа. После того, как вы выключите питание, эти настройки сбросятся и разбираться с тактированием вам все же придется. Цитата(thamjell @ Sep 1 2015, 12:01)  либо же в переходнике, хотя он успешно переправлял сам себе символы А посмотрите на уровни его сигналов в таком режиме. Возможно ему просто не хватает уровня лог.1 на выходе вашего процессора.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 1 2015, 10:59
|
Частый гость
 
Группа: Участник
Сообщений: 110
Регистрация: 23-06-14
Пользователь №: 82 030

|
Цитата(Сергей Борщ @ Sep 1 2015, 13:48)  Что за переходник у вас такой чудный? Нет, в самом деле у RS-232 уровень лог.1 равен -12 В, а уровень лог. нуля - +12 В, но втыкать выход УАСПП напрямую в RS-232 нельзя, для согласования существуют микросхемы согласования типа MAX202 и ее многочисленных аналогов/клонов. Переходник - Orient USS-101N, я не сам собирал, а купил готовый. Хотя чувствую, что придётся собирать самому, раз этот выдаёт такое. В принципе, картинка складывается. Переходник не тот. Он преобразует 12 вольт от RS232 в 5 вольт на USB. Я отдаю ему 3 вольта, и отсюда такая чушь получается на выходе. Так я ещё никогда не ошибался  И да, конечно же, большое спасибо за совет. Некоторое время не мог осознать, что допустил такую глупую ошибку. P.S. хотя ещё не вечер, вдруг потом ещё ошибки всплывут
Сообщение отредактировал thamjell - Sep 1 2015, 11:25
|
|
|
|
|
Sep 1 2015, 11:32
|
Частый гость
 
Группа: Участник
Сообщений: 110
Регистрация: 23-06-14
Пользователь №: 82 030

|
Цитата(ViKo @ Sep 1 2015, 14:28)  Так вы поняли, что к этому (нормальному) переходнику вам нужно добавить преобразователи 3V <-> +-12V на стороне микроконтроллера? Или влезть в нутро переходника, и там ... ломать. Да, естественно понял. И понял, почему этот переходник исправно работал с оборудованием, на котором разъёмы RS232 стоят - там-то уровни напряжений нормальные, а не 3 вольта, как у меня. Я не буду лезть внутрь переходника, сейчас поищу готовые переходники для таких случаев. Хотя мне кажется, что не найду и скорее всего буду сам делать переходник 3V <-> +-12V.
|
|
|
|
|
Sep 1 2015, 11:40
|
Частый гость
 
Группа: Участник
Сообщений: 110
Регистрация: 23-06-14
Пользователь №: 82 030

|
Цитата(ViKo @ Sep 1 2015, 14:36)  ... и инвертированные. 0 преобразовывается в +12 В, а 1 в -12 В. В-принципе, можно обойтись и +- 5 В сигналами. Даже и +-3 В. Да что там, и 0 +3 может работать (но инвертировать нужно все равно). Вот этот момент поподробнее, как я понял - вы же про логический ноль? Поскольку таковым на выходе УАСПП для меня является +3В. Ну и 0 вольт на выходе УАСПП - это для меня лог. единичка, соответственно. А не, всё понял. Лог. единичка - это +3 вольта на выходе, её инвертируем и получаем -12 вольт - соответствует лог. единичке для приёмника (терминала).
Сообщение отредактировал thamjell - Sep 1 2015, 11:46
|
|
|
|
|
Sep 1 2015, 11:53
|
Частый гость
 
Группа: Участник
Сообщений: 110
Регистрация: 23-06-14
Пользователь №: 82 030

|
Цитата(ViKo @ Sep 1 2015, 14:51)  Правильно. То есть, в вашем переходнике не хватает всего лишь инверсии сигналов. Ну я попытаюсь сделать ещё, чтобы логическим уровням в +-12 вольт соответствовало. Спасибо за помощь.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|