Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не работает USART на STM32F100RB
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
thamjell
Здравствуйте, столкнулся с проблемой. Скажу сразу, я не первый день над её разрешением думаю, всё перепробовал и только сейчас решил обратиться сюда - может кто-нибудь и сталкивался.
Дело в чём: хочу организовать обмен данными по COM-порту на STM32-VLDiscovery (в основе данной отладочной платы лежит STM32F100RB). Ну ок, прочитал необходимые разделы в Reference Manual, посмотрел примеры в интернете и решил делать. Сначала пошёл лёгким путём, решив отправлять один символ с микроконтроллера через небольшие промежутки времени (ну а потом организовал бы полноценный обмен). Использую keil uvision5. Написал программу с использованием библиотеки STDPeriph. Написал. Он присылает - но не те символы. Решил найти, в чём проблема, не нашёл. Решив, что во всём виновата библиотека biggrin.gif - полез в референс мануал с описанием регистров порта ввода/вывода и USART. Написал программу, без использования STDPeriph (её код ниже). Результат - тот же.
Ну и решил искать, в чём проблема. Первая мысль - то, что baudrate не тот. Измерил частоту SYSCLK - 24 МГц, потом решил строго установить делители частоты для шин AHB (крепится к SYSCLK) и APB2 (на ней висят GPIOA(PA9 у данного порта - передатчик USART) и USART1). Ставил на эту шину и 24 МГц, и 6 МГц - результат тот же. Решил измерить выходной бодрейт с помощью осциллографа rolleyes.gif - тут тоже всё нормально. Потом подумал, что во всём виновата терминальная программа на компе, поставил другую - не то, не в этом проблема. Далее решил, что переходник 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

Какой-то связи между вышеуказанными двоичными числами, я не вижу. И это меня вообще в тупик ставит.
ViKo
Биты обычно по линии передаются, начиная с младшего. (У вас настройки не нашел. Пройдитесь по всем битам в управляющих регистрах.)
Если так, то почти все нормально. Может, в настройках терминальной программы указано наоборот?
Задайте 2 стопа. Надежнее искать начало и конец передачи будет, хотя бы визуально.
thamjell
Цитата(ViKo @ Sep 1 2015, 10:51) *
Биты обычно по линии передаются, начиная с младшего. (У вас настройки не нашел. Пройдитесь по всем битам в управляющих регистрах.)
Если так, то почти все нормально. Может, в настройках терминальной программы указано наоборот?
Задайте 2 стопа. Надежнее искать начало и конец передачи будет, хотя бы визуально.

Настройки порядка битов в регистрах не нашёл, но в терминальной программе есть функция "Inverse bits". Вместо 4F (01001111) стал выдавать F2 (11110010), а должен был выдавать символ "a". 2 стопа задавал, эффекта нет sad.gif
P.S. "a" - это 01100001, на всякий случай
ViKo
Цитата(thamjell @ Sep 1 2015, 11:04) *
P.S. "a" - это 01100001, на всякий случай

Замечательно! И осциллограф вам ее показал. А терминальная программа обманула. Выводы?
thamjell
Цитата(ViKo @ Sep 1 2015, 11:13) *
Замечательно! И осциллограф вам ее показал. А терминальная программа обманула. Выводы?

Ого. Странно, что я не заметил этого сразу. Я терминальным программам доверял, у меня их две поставлено. Ладно, буду сейчас с ними разбираться. Спасибо за помощь!
Что в итоге получилось - ещё напишу)
Сергей Борщ
Больше всего эжто похоже на несовпадение скоростей. Я не вижу у вас в программе настройки тактирования на 24 МГц, от которых вы считаете коэффициент деления генератора битовой скорости.
thamjell
Цитата(Сергей Борщ @ Sep 1 2015, 11:48) *
Больше всего эжто похоже на несовпадение скоростей. Я не вижу у вас в программе настройки тактирования на 24 МГц, от которых вы считаете коэффициент деления генератора битовой скорости.

Я не знал, как определить данную частоту и сделал программу, которая считывает частоту с вывода MCO. Просмотрев регистры в режиме отладки, я увидел, что в качестве источника тактовой частоты используется PLL, проверил частоту с пина MCO при помощи осциллографа - показало 12 МГц, относительно к PLL он показывает частоту PLL, делённую на два (см. картинку), отсюда такие и выводы.

Прикрепляю ещё одну картинку, это бит на экране осциллографа, его длительность - где-то около 105 мкс. Это даёт бодрейт 9524. Так что думаю, что тут ошибки нету. А вот с терминальными программами, вероятно есть ошибки, либо же в переходнике, хотя он успешно переправлял сам себе символы, да и с оборудованием нормально работал.

Может быть стоит поработать с CTS и RTS? А то они отключены у меня.
thamjell
Так ничего с терминальными программами не получилось - одно и то же. Видимо дело в работе с CTS и RTS, другого я просто не вижу. Пробовал подключать напрямую, к COM-порту в компьютере - тоже ерунда выходит( поэтому скорее всего и не в переходнике проблема.
ViKo
Я пользуюсь программой HTerm. Настройки CTS, RTS не трогаю. Они не должны влиять, если сигналов нет.
Вы сигналы смотрите до преобразователя уровней 3 В <-> 12 B? Какие сигналы после них?
thamjell
Цитата(ViKo @ Sep 1 2015, 13:24) *
Я пользуюсь программой HTerm. Настройки CTS, RTS не трогаю. Они не должны влиять, если сигналов нет.
Вы сигналы смотрите до преобразователя уровней 3 В <-> 12 B? Какие сигналы после них?

Возможно, я нашёл в чём проблема. Я сделал, чтобы микроконтроллер выдавал числа 0xFF. По идее - должны выделяться только стоповые биты (логический ноль). А терминал мне выдал 0х00.
Записал в микроконтроллер 0x00 - терминал выдал 0xFF (этот случай сопровождаю фото с осциллографа).
Такое ощущение, что логическая "1" для микроконтроллера - это логический "0" для терминала. Посмотрел по остальным символам - вроде как тоже это объясняет. Как это исправить можно?
Сергей Борщ
Цитата(thamjell @ Sep 1 2015, 12:01) *
Я не знал, как определить данную частоту и сделал программу, которая считывает частоту с вывода MCO. Просмотрев регистры в режиме отладки, я увидел, что в качестве источника тактовой частоты используется PLL, проверил частоту с пина MCO при помощи осциллографа - показало 12 МГц, относительно к PLL он показывает частоту PLL, делённую на два (см. картинку), отсюда такие и выводы.
Эту частоту настроила предыдущая загруженная программа. После того, как вы выключите питание, эти настройки сбросятся и разбираться с тактированием вам все же придется.

Цитата(thamjell @ Sep 1 2015, 12:01) *
либо же в переходнике, хотя он успешно переправлял сам себе символы
А посмотрите на уровни его сигналов в таком режиме. Возможно ему просто не хватает уровня лог.1 на выходе вашего процессора.
ViKo
Цитата(thamjell @ Sep 1 2015, 13:41) *
Такое ощущение, что логическая "1" для микроконтроллера - это логический "0" для терминала. Посмотрел по остальным символам - вроде как тоже это объясняет. Как это исправить можно?

Так преобразователи есть или как? Сначала понять, как сделано, а потом думать, как исправить. rolleyes.gif
Сергей Борщ
Цитата(thamjell @ Sep 1 2015, 13:41) *
Такое ощущение, что логическая "1" для микроконтроллера - это логический "0" для терминала.
Что за переходник у вас такой чудный? Нет, в самом деле у RS-232 уровень лог.1 равен -12 В, а уровень лог. нуля - +12 В, но втыкать выход УАСПП напрямую в RS-232 нельзя, для согласования существуют микросхемы согласования типа MAX202 и ее многочисленных аналогов/клонов.
thamjell
Цитата(Сергей Борщ @ Sep 1 2015, 13:48) *
Что за переходник у вас такой чудный? Нет, в самом деле у RS-232 уровень лог.1 равен -12 В, а уровень лог. нуля - +12 В, но втыкать выход УАСПП напрямую в RS-232 нельзя, для согласования существуют микросхемы согласования типа MAX202 и ее многочисленных аналогов/клонов.

Переходник - Orient USS-101N, я не сам собирал, а купил готовый. Хотя чувствую, что придётся собирать самому, раз этот выдаёт такое.
В принципе, картинка складывается. Переходник не тот. Он преобразует 12 вольт от RS232 в 5 вольт на USB. Я отдаю ему 3 вольта, и отсюда такая чушь получается на выходе. Так я ещё никогда не ошибался laugh.gif

И да, конечно же, большое спасибо за совет. Некоторое время не мог осознать, что допустил такую глупую ошибку.
P.S. хотя ещё не вечер, вдруг потом ещё ошибки всплывут laugh.gif
ViKo
Цитата(thamjell @ Sep 1 2015, 13:59) *
Переходник не тот. Он преобразует 12 вольт от RS232 в 5 вольт на USB. Я отдаю ему 3 вольта, и отсюда такая чушь получается на выходе. Так я ещё никогда не ошибался laugh.gif

И да, конечно же, большое спасибо за совет. Некоторое время не мог осознать, что допустил такую глупую ошибку.
P.S. хотя ещё не вечер, вдруг потом ещё ошибки всплывут laugh.gif

Так вы поняли, что к этому (нормальному) переходнику вам нужно добавить преобразователи 3V <-> +-12V на стороне микроконтроллера? Или влезть в нутро переходника, и там ... ломать.
thamjell
Цитата(ViKo @ Sep 1 2015, 14:28) *
Так вы поняли, что к этому (нормальному) переходнику вам нужно добавить преобразователи 3V <-> +-12V на стороне микроконтроллера? Или влезть в нутро переходника, и там ... ломать.

Да, естественно понял. И понял, почему этот переходник исправно работал с оборудованием, на котором разъёмы RS232 стоят - там-то уровни напряжений нормальные, а не 3 вольта, как у меня.
Я не буду лезть внутрь переходника, сейчас поищу готовые переходники для таких случаев. Хотя мне кажется, что не найду и скорее всего буду сам делать переходник 3V <-> +-12V.
ViKo
Цитата(thamjell @ Sep 1 2015, 14:32) *
на котором разъёмы RS232 стоят - там-то уровни напряжений нормальные, а не 3 вольта, как у меня.

... и инвертированные. 0 преобразовывается в +12 В, а 1 в -12 В. В-принципе, можно обойтись и +- 5 В сигналами. Даже и +-3 В. Да что там, и 0 +3 может работать (у вас же работает :-) ), но инвертировать нужно все равно).
thamjell
Цитата(ViKo @ Sep 1 2015, 14:36) *
... и инвертированные. 0 преобразовывается в +12 В, а 1 в -12 В. В-принципе, можно обойтись и +- 5 В сигналами. Даже и +-3 В. Да что там, и 0 +3 может работать (но инвертировать нужно все равно).

Вот этот момент поподробнее, как я понял - вы же про логический ноль? Поскольку таковым на выходе УАСПП для меня является +3В. Ну и 0 вольт на выходе УАСПП - это для меня лог. единичка, соответственно.
А не, всё понял. Лог. единичка - это +3 вольта на выходе, её инвертируем и получаем -12 вольт - соответствует лог. единичке для приёмника (терминала).
ViKo
Цитата(thamjell @ Sep 1 2015, 14:40) *
Лог. единичка - это +3 вольта на выходе, её инвертируем и получаем -12 вольт - соответствует лог. единичке для приёмника (терминала).

Правильно. То есть, в вашем переходнике не хватает всего лишь инверсии сигналов.
thamjell
Цитата(ViKo @ Sep 1 2015, 14:51) *
Правильно. То есть, в вашем переходнике не хватает всего лишь инверсии сигналов.

Ну я попытаюсь сделать ещё, чтобы логическим уровням в +-12 вольт соответствовало. Спасибо за помощь.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.