Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: UART2 на STM32F100C4 сплошные глюки :')
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Bob176

Не могу понять в чём дело.. процессор STM32F100C4 инициализирую при помощи файла STM32_Init.c
пытаюсь принять и передать байты по прерываниям...

принимать удаётся, только все принятые данные почему то смещены на 0х80
т.е. если передается
1 то принимаю 129 (0х81)
2 то принимаю 130 (0х82)
и Т.Д.

а вот передать через прерывание вообще не получается...
точнее .. если не через прерывания, то байт передаётся.. правда данные искажены..
если ставлю галочку в мастере TXE Interrupt Enable , по вообще всё виснет

помогите разобраться



инициализирую теперь так:
Код
                    void USART_configuration(void)
{
  //Включение тактирования
  RCC->APB2ENR |=   RCC_APB2ENR_IOPAEN;                //Тактирование GPIO
  RCC->APB2ENR |=   RCC_APB2ENR_AFIOEN;                //Тактирование альтернативных функций GPIO
  RCC->APB1ENR |=   RCC_APB1ENR_USART2EN;              //Тактирование USART2
  //Конфигурирование PORTA.2 для TX; PORTA.3 для RX
      GPIOA->CRL   &= ~(0xFFUL  << 8);                      // Clear PA2, PA3
      GPIOA->CRL   |=  (0x0BUL  << 8);                      // USART2 Tx (PA2)  alternate output push-pull
      GPIOA->CRL   |=  (0x04UL  << 12);                     // USART2 Rx (PA3)  input floating

  //Задание режима работы
  USART2->BRR   =   0x0341;                            //Cкорость обмена 9600 бод
  USART2->CR1  &=  ~USART_CR1_M;                       //8 бит данных
  USART2->CR2  &=  ~USART_CR2_STOP;                    //Предочистка числа стоп-битов
  USART2->CR2  |=   USART_CR2_STOP_0;                  //Количество стоп-битов: 2
  //Управление работой
  USART2->CR1  |=   USART_CR1_UE;                      //Включение модуля USART2
  USART2->CR1  |=   USART_CR1_TE;                      //Включение передатчика
  USART2->CR1  |=   USART_CR1_RE;                      //Включение приемника
  //Разрешить прерывания
  //NVIC_EnableIRQ (USART2_IRQn);                        //Прерывания USART2
  // USART2->CR1  |= USART_CR1_TCIE;                      //Прерывание по завершении передачи
  USART2->CR1  |= USART_CR1_RXNEIE;                    //Прерывание по завершении приема
NVIC->ISER[1]  = (1 << (USART2_IRQn & 0x1F));   // enable interrupt

  USART_ITConfig(USART2, USART_IT_TC, DISABLE);
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);


прерывание

Код
           void USART2_IRQHandler(void)
{                  
  volatile unsigned int IIR;
    
       IIR = USART2->SR;

if(IIR & USART_IT_RXNE)  
   {
   USART2->SR &= ~USART_IT_RXNE;              // clear interrupt
    
        if(usart2.rxcnt>(BUF_SZ-2))    usart2.rxcnt=0;
              
    usart2.buffer[usart2.rxcnt++] =  USART_ReceiveData (USART2);

                  
        usart2.delay=0;

if(usart2.rxcnt>7)usart2.rxgap=1;       // принял всю посылку
    }


ф-я маin

Код
stm32_Init ();       // STM32 setup

USART_configuration();
while (1)
  {      
    if(usart2.rxgap==1)                        
      {        
        //   if (usart2.buffer[0]==129)
          // {      
                GPIOB->BSRR = GPIO_Pin_1; // передача        
    
//       rx_Data=usart2.buffer[1];


        //USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
        // USART_ITConfig(USART2, USART_IT_TC, ENABLE);
            Delay(100);
    
            USART_SendData(USART2, 1);

               
       usart2.rxcnt=0;
       usart2.rxtimer=0;
       usart2.delay=0;
       usart2.rxgap=0;
   GPIOB->BRR = GPIO_Pin_1;
      }


приём остался таким же
1 то принимаю 129 (0х81)
2 то принимаю 130 (0х82)
и Т.Д.

а при передаче байта отправляется мусор !!!

и тоже если в конфигурации разрешить
USART2->CR1 |= USART_CR1_TCIE; //Прерывание по завершении передачи
то уже ничего не принимает ... похоже висит.


посоветуйте, что проверить? как ещё настроить?

осциллографом смотрел, битики при передаче бегут rolleyes.gif до ST485 доходят crying.gif
hatchet
Попробуйте настроить UART через стандартную stm'овскую либу.
SSerge
Зря Вы в обработчике прерываний USART_IT_RXNE используете, эти ..... его очень оригинально определили.
И он нифига не совпадает ни с USART_SR_RXNE ни с USART_FLAG_RXNE.
PoReX
Вы там случаем контролем четности не балуетесь? А тож смотрите, если он включен, то данных будет 7 бит, а восьмой бит четности.
Bob176
Цитата(PoReX @ Aug 28 2012, 17:31) *
Вы там случаем контролем четности не балуетесь? А тож смотрите, если он включен, то данных будет 7 бит, а восьмой бит четности.

laughing.gif нет не балуюсь, не дошёл ещё до чётности, но Вы правы, на это надо обратить внимание. сегодня вечером займусь cranky.gif
Bob176
Ну что же помоему до меня дошло rolleyes.gif


я тактирую от внутреннего генератора 8 МГц. похоже отсуда и все глюки!!!

как считает общественность?

у меня стоит на макетке 32кГц внешний кварц Можно ли им обойтись?
scifi
Цитата(Bob176 @ Aug 29 2012, 09:28) *
я тактирую от внутреннего генератора 8 МГц. похоже отсуда и все глюки!!!
как считает общественность?

Тактирую от него же, глюков нет. По паспорту, да и по жизни отклонение частоты внутреннего генератора - в допустимых пределах для UART. Кстати, это несложно проверить осциллографом: измерьте частоту следования битов.
spectral1989
какой терминал и все ли там правильно стоит? baudrate, stop bits, data bits, parity
_Pasha
Цитата(Bob176 @ Aug 29 2012, 08:28) *
у меня стоит на макетке 32кГц внешний кварц Можно ли им обойтись?

Нельзя.
Bob176
Цитата(scifi @ Aug 29 2012, 08:42) *
Тактирую от него же, глюков нет.

crying.gif
Цитата(scifi @ Aug 29 2012, 08:42) *
Кстати, это несложно проверить осциллографом: измерьте частоту следования битов.

... хорошо измерю ...
Цитата(spectral1989 @ Aug 29 2012, 09:03) *
какой терминал и все ли там правильно стоит? baudrate, stop bits, data bits, parity


.. Терминал проверенный и стоит там всё правильно!

неужели проблема в железе ... wacko.gif

может у кого найдётся рабочий пример UARTа на stm32F100C4 ?
не важно на прерываниях или без ..
scifi
Цитата(Bob176 @ Aug 29 2012, 12:32) *
может у кого найдётся рабочий пример UARTа на stm32F100C4 ?

Пожалуйста:
CODE
#include "uart.h"
#include "stm32f1regs.h"
#include "assert_static.h"

#define USART_BASE USART3_BASE
#define USART_SR REG32(USART_BASE + 0)
#define USART_DR REG32(USART_BASE + 4)
#define USART_BRR REG32(USART_BASE + 8)
#define USART_CR1 REG32(USART_BASE + 0xC)
#define USART_CR2 REG32(USART_BASE + 0x10)
#define USART_CR3 REG32(USART_BASE + 0x14)

#define TXFIFOSIZE 32
#define RXFIFOSIZE 32
#define BAUDREG (24000000 / 100000) /* 100 kbps @ 24 MHz */

static uint8_t txfifo[TXFIFOSIZE];
static uint8_t volatile rxfifo[RXFIFOSIZE];
static unsigned int volatile txtail, rxhead;
static unsigned int txhead, rxtail;

void
uart_init(int prio)
{
assert_static(IS_PWR_OF_TWO(TXFIFOSIZE));
assert_static(IS_PWR_OF_TWO(RXFIFOSIZE));
REGBIT(RCC_APB1ENR, 18) = 1; /* enable clocking of USART3 */
REGBIT(RCC_APB2ENR, 3) = 1; /* enable clocking of PORT B */
USART_BRR = BAUDREG;
USART_CR1 = (1 << 13) /* USART enable */
| (1 << 5) /* RXNE irq enable */
| (1 << 3) /* transmitter enable */
| (1 << 2);/* receiver enable */
USART_CR3 = 8; /* select half duplex */
NVIC_IP[39 / 4] |= (prio << (9 * (39 % 4)));
NVIC_SETENA1 = (1 << (39 - 32));
/* configure PB10 as alternate function push-pull 2 MHz */
GPIOB_CRH = (GPIOB_CRH & 0xFFFFF0FF) | 0x00000A00;
}

__root void
usart_irq_handler(void)
{
uint32_t status;
status = USART_SR;
if (status & (1 << 5)) /* RXNE */
{
int head;
head = rxhead;
if ((head - rxtail) != RXFIFOSIZE)
{
rxfifo[head & (RXFIFOSIZE - 1)] = USART_DR;
rxhead = head + 1;
}
else
{
(void)USART_DR;
}
}
if (status & (1 << 7)) /* TXE */
{
int tail;
tail = txtail;
if (txhead != tail)
{
USART_DR = txfifo[tail & (TXFIFOSIZE - 1)];
txtail = tail + 1;
}
else
{
USART_CR1 &= ~(1 << 7); /* disable TXNE irq */
}
}
}

int
uart_txfree(void)
{
return TXFIFOSIZE - (txhead - txtail);
}

int
uart_txfull(void)
{
return txhead - txtail;
}

void
uart_putbyte(uint8_t byte)
{
while (uart_txfree() == 0)
{
/* wait for free space in Tx FIFO */
}
txfifo[txhead & (TXFIFOSIZE - 1)] = byte;
txhead++;
USART_CR1 |= (1 << 7); /* enable TXNE irq */
}

int
uart_rxcount(void)
{
return rxhead - rxtail;
}

uint8_t
uart_getbyte(void)
{
uint8_t ret;
ret = rxfifo[rxtail & (RXFIFOSIZE - 1)];
rxtail++;
return ret;
}
Bob176
Цитата(scifi @ Aug 29 2012, 12:16) *
Пожалуйста:

спасибо за пример,
Код
USART_CR3 = 8; /* select half duplex */

может быть в этом проблема ? ... вечером попробую
scifi
Цитата(Bob176 @ Aug 29 2012, 15:59) *
может быть в этом проблема ? ... вечером попробую

Нет. У меня используется полудуплексный режим. Вам он едва ли понадобится.
И вообще, чтение мануала никто не отменял. Бездумное копирование кода не есть комильфо.
ViKo
Для scifi
У вас в коде есть строчка
(void)USART_DR;
Как это работает?
Bob176
Цитата(scifi @ Aug 29 2012, 15:33) *
У меня используется полудуплексный режим. Вам он едва ли понадобится.


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


А бездумное копирование кода - всегда не комильфо laughing.gif


scifi
Цитата(ViKo @ Aug 29 2012, 16:50) *
У вас в коде есть строчка
(void)USART_DR;
Как это работает?

Прочитать регистр и выкинуть результат. Можно просто "USART_DR;", но приведение к void нагляднее. Где-то читал статейку, где это разжёвано. Если найду, приложу ссылку. Читал стандарт C99 - да, всё путём, так и должно работать, хотя кому-то покажется странным.

Update:
Вот интересная статья на эту тему. Краткое содержание: по стандарту Си код должен работать, но на практике он работает не со всеми компиляторами. По стандарту Си++ - вообще какой-то туман, и поведение компиляторов различается ещё сильнее.
Получается, что если рассчитывать не на сферический компилятор в вакууме, которые следует стандарту до последней запятой, а на обычные глючные компиляторы, то лучше использовать более развёрнутую конструкцию с присвоением значения временной переменной.
sidy
Т.е. если Вы находитесь в режиме передачи, но что-то приняли то таким образом очищаете принятые данные?
scifi
Цитата(sidy @ Aug 29 2012, 18:20) *
Т.е. если Вы находитесь в режиме передачи, но что-то приняли то таким образом очищаете принятые данные?

В коде это видно: если в приёмном буфере нет места, то выбросить принятый байт. Это нештатная ситуация.
ViKo
Цитата(scifi @ Aug 29 2012, 16:40) *
Краткое содержание: по стандарту Си код должен работать, но на практике он работает не со всеми компиляторами. По стандарту Си++ - вообще какой-то туман, и поведение компиляторов различается ещё сильнее.
Получается, что если рассчитывать не на сферический компилятор в вакууме, которые следует стандарту до последней запятой, а на обычные глючные компиляторы, то лучше использовать более развёрнутую конструкцию с присвоением значения временной переменной.

Спасибо. В-общем, "Не надо, как лучше. Надо, как положено." (с)
Bob176
Цитата(SSerge @ Aug 28 2012, 12:49) *
Зря Вы в обработчике прерываний USART_IT_RXNE используете, эти ..... его очень оригинально определили.
И он нифига не совпадает ни с USART_SR_RXNE ни с USART_FLAG_RXNE.


спасибо, SSerge теперь не зависает, хотя передача пока так и не работает crying.gif

.. разбираюсь дальше...


ну вот laughing.gif уже лучше!!!

данные передаются только ..... как и прежде

передаю 1 - принимаю 129 (0х81)
передаю 2 - принимаю 130 (0х82)
передаю 3 - принимаю 131 (0х83)
...

при передаче
передаю несколько байт значения 129 а принимает терминал то как 129 (0x81), то как 1 (0x80) !!!

что подскажете?
vlad_new
Цитата(Bob176 @ Aug 30 2012, 01:05) *
данные передаются только ..... как и прежде

передаю 1 - принимаю 129 (0х81)
передаю 2 - принимаю 130 (0х82)
передаю 3 - принимаю 131 (0х83)
...

при передаче
передаю несколько байт значения 129 а принимает терминал то как 129 (0x81), то как 1 (0x80) !!!

что подскажете?


USART2->CR2 |= USART_CR2_STOP_0; //Количество стоп-битов: 2
Как то странно выглядет. Может все же ..._STOP_2 ?
Хотя в ST-эшной библиотеке на F0 все еще прикольней выглядет:
#define USART_StopBits_2 ((uint32_t)USART_CR2_STOP_1)
sm.gif

Bob176
Цитата(vlad_new @ Aug 30 2012, 02:02) *
#define USART_StopBits_2 ((uint32_t)USART_CR2_STOP_1)

biggrin.gif biggrin.gif biggrin.gif

вечером проверю, хотя... думаю дело не в этом. Надо посмотреть подтяжку у TX & RX
Bob176

мнда... и всё же паритет!!! rolleyes.gif


всем спасибо bb-offtopic.gif

Bob176
ещё одна проблемка нарисовалась...

до скорости обмена 9600 всё работает хорошо. и принимаю и передаю как надо, а вот если увеличиваю скорость обмена, то принимается всё корректно, а при передаче передаётся ещё один ненужный байт!

скорость 9600
Send: 01-04-00-01-00-01-60-0A (8 bytes)
Recv: 01-04-02-65-64-93-8B (7 bytes)
Error: NONE; Data = 65-64; Time: 46

скорость 19200
Send: 01-04-00-01-00-01-60-0A (8 bytes)
Recv: 01-04-02-65-64-93-8B-FF (8 bytes)
Error: CRC+LENGTH; Data = NOT DETECTED; Time: 46

может кто чего подскажет? где копать?
Сергей Борщ
QUOTE (Bob176 @ Sep 17 2012, 21:59) *
где копать?
В программе. 115200, 9600, 57600 - полет нормальный.
_Pasha
Цитата(Bob176 @ Sep 17 2012, 21:59) *
до скорости обмена 9600 всё работает хорошо

импульс, коорый воспринимается как старт-бит?
А что у Вас за схема по RS-у ?
Bob176
Цитата(_Pasha @ Sep 17 2012, 23:06) *
импульс, коорый воспринимается как старт-бит?

это одиночная посылка

Цитата(_Pasha @ Sep 17 2012, 23:06) *
что у Вас за схема по RS-у ?


оптопары, управление потоком через транзистор инвертируется.
DmitryM
Цитата(Bob176 @ Sep 18 2012, 14:06) *
оптопары, управление потоком через транзистор инвертируется.

А скорострельность оптопары?? Чтобы 115200 проходило нужно тщательно отбирать оптопары. Типовое время отклика 18-20мкс, а это уже соизмеримо с длительностью импульса на 115200.
MBR
Цитата(Bob176 @ Sep 17 2012, 22:59) *
может кто чего подскажет? где копать?

а на чем без кода гадать?
Bob176
Цитата(DmitryM @ Sep 18 2012, 14:16) *
А скорострельность оптопары?? Чтобы 115200 проходило нужно тщательно отбирать оптопары. Типовое время отклика 18-20мкс, а это уже соизмеримо с длительностью импульса на 115200.

оптопары скорострельные H11L1

Цитата
а на чем без кода гадать?

мне идея нужна...

MBR
Цитата(Bob176 @ Sep 18 2012, 15:05) *
мне идея нужна...

Ну, не хотите по существу, я тоже в абстракцию уйду sm.gif Идея проста - написание своих велосипедов без достаточно вдумчивого чтения манов чревато глюками и потерянным временем sm.gif
Bob176
Цитата(MBR @ Sep 18 2012, 15:34) *
Ну, не хотите по существу, я тоже в абстракцию уйду sm.gif Идея проста - написание своих велосипедов без достаточно вдумчивого чтения манов чревато глюками и потерянным временем sm.gif

уважаемый MBR вы считаете проблема в коде? в инициализации? в прерывании? в начале поста я выкладывал исходники.. особенно в них ничего не поменялось... данные принимаются верно, значит скорость задана правильно, на низкой частоте все работает корректно... что может привести к тому, что на высокой частоте передаётся ещё один байт мне пока не понятно ... , вот и интересуюсь, может кто уже сталкивался с такой проблемой... или натолкнёт идейкой на решение ..
scifi
Цитата(Bob176 @ Sep 18 2012, 16:20) *
или натолкнёт идейкой на решение ..

Есть идейка: потыкайте осциллографом вашу схему. К тому же вы упоминали про полудуплекс: вдруг при переключении режима приём-передача на линии образуется выброс? Ну и вообще полезно убедиться, что проблема не в железе, прежде чем нырять в софт.
MBR
Цитата(Bob176 @ Sep 18 2012, 16:20) *
в начале поста я выкладывал исходники.. особенно в них ничего не поменялось...

Там была ссылка на нерабочий вариант.

scifi, скорее всего, прав насчет полудуплекса. Правильная логика отправки должна быть следующая: разрешаем TXE, делаем отправку. После отправки последнего байта в обработчике запрещаем TXE, разрешаем TC. И только когда снова придем в обработчик TC - запрещаем TC и трансмиттер.

Но Ваша лень сделать копипасту превращает это лишь в предположения. Я могу дать ссылку на мой рабочий исходник с полудуплексом для F2 - там разница лишь в установке baud rate, при передаче данных регистры те же.
DmitryM
Цитата(Bob176 @ Sep 18 2012, 15:05) *
оптопары скорострельные H11L1

Очень скорострельные biggrin.gif
Turn–On Time 1,2 (max 4) us
Turn–Off Time 1,2 (max 4) us
when RL = 270R If=1,2mA

А теперь посчитаем грубо 1/115200=8,68us, что остается в остатке?
Осциллограф и еще раз осциллограф.
Bob176
Цитата(scifi @ Sep 18 2012, 16:44) *
Есть идейка: потыкайте осциллографом вашу схему. К тому же вы упоминали про полудуплекс: вдруг при переключении режима приём-передача на линии образуется выброс? Ну и вообще полезно убедиться, что проблема не в железе, прежде чем нырять в софт.


Да, scifi, хорошо бы посмотреть осциллографом, да у меня дома древний, аналоговый... сложно им что то увидеть, да и JTAGA на плате нет и отладчик Keilа этот проц не поддерживает ... вот и мучаюсь... rolleyes.gif

про полудуплекс ... полудуплекс - подразумевает передачу данных и приём в разные моменты времени и раньше я думал, что что у меня именно такой случай, а оказалось нет ... полный дуплекс smile3046.gif . В данном случае полудуплекс получится при передаче и приёме по одному проводу и разделении во времени..., а я всёж использую 2 провода, хотя и преобразую потом в RS-485

да, в железе может быть проблема, полностью согласен.. надеюсь сегодня вечером доберусь до платы и продолжу эксперименты biggrin.gif

Цитата
Очень скорострельные biggrin.gif

DmitryM а Вы что применяете?
..... хотя, я думаю оптопары справляются, ведь данные не искажаются, а появляется ещё один байт ...
DmitryM
Цитата(Bob176 @ Sep 19 2012, 15:12) *
В данном случае полудуплекс получится при передаче и приёме по одному проводу и разделении во времени..., а я всёж использую 2 провода, хотя и преобразую потом в RS-485

А в RS485 у Вас сколько проводов? Вы ж управляете включением-выключением приемника/передатчика RS485, вот Вам и полудуплекс.
Кстати, не забыли, что у многих приемопередатчиков RS485 выход приемника переходит в Z-состояние. Там хоть подтяжка есть? или болтается в воздухе?
Цитата
DmitryM а Вы что применяете?
..... хотя, я думаю оптопары справляются, ведь данные не искажаются, а появляется ещё один байт ...

ADUM1201, например.
Bob176
Цитата(DmitryM @ Sep 19 2012, 17:19) *
А в RS485 у Вас сколько проводов? Вы ж управляете включением-выключением приемника/передатчика RS485, вот Вам и полудуплекс.


DmitryM, я раньше тоже так думал, но в применении к данному случаю, полудуплекс - если и приём и передача ведутся по одному проводу Тх !

на выходе приемника подтяжка есть.

ADUM1201 - уж больно дорогое решение
Bob176
ну всё, разобрался! laughing.gif

передавал один лишний байт, была ошибка в программе ... а прерывание всё честно отрабатывало

теперь всё ок!!!

DmitryM , scifi и всем спасибо !!!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.