Перейти к содержанию
    

Не могу запустить USART на stm32h743

Не могу запустить USART на stm32h743. Нет сигнала на выходе TX

Что сделал:

Скрытый текст

  /*настройка uart + DMA для внешнех блоков*/
  RCC->APB1LENR |= RCC_APB1LENR_USART3EN; // подключаем USART 3 к шине ABP1
  while(!(RCC->APB1LENR & RCC_APB1LENR_USART3EN));// ждем чтобы гарантировано подключился

  SET_BIT(RCC->AHB4ENR, RCC_AHB4ENR_GPIODEN);
  GPIOD->MODER |= 0x2 << GPIO_MODER_MODE8_Pos; // перевод порта на альтернативную функцию в частности USART_TX
  GPIOD->MODER |= 0x2 << GPIO_MODER_MODE9_Pos; // перевод порта на альтернативную функцию в частности USART_RX
  GPIOD->OSPEEDR |= 0x2 << GPIO_OSPEEDR_OSPEED8_Pos; // настройка скорости фронта USART скорость наибольшая
  GPIOD->OSPEEDR |= 0x2 << GPIO_OSPEEDR_OSPEED9_Pos; // настройка скорости фронта USART
  GPIOD->PUPDR &= 0x00 << GPIO_PUPDR_PUPD8_Pos; // отключение подтяжки
  GPIOD->PUPDR &= 0x00 << GPIO_PUPDR_PUPD9_Pos; // отключение подтяжки
  GPIOD->AFR[1] |= 0x7 << GPIO_AFRH_AFSEL8_Pos | 0x7 << GPIO_AFRH_AFSEL9_Pos;  // переключение мультиплексора на альтернативные выводы AF7

  USART3->CR1 &= ~USART_CR1_UE; // отключение USART 3 для настройки
  while(USART3->CR1 & USART_CR1_UE); // проверяем что бит включения USART сброшен
  USART3->CR2 = 0x00;
  /*USART3->CR2 = 0x00 << USART_CR2_ADD_Pos | ~USART_CR2_RTOEN | 0x00 << USART_CR2_ABRMODE_Pos | ~USART_CR2_ABREN | ~USART_CR2_MSBFIRST | ~USART_CR2_DATAINV | \
		  ~USART_CR2_TXINV | ~USART_CR2_RXINV | ~USART_CR2_SWAP | ~USART_CR2_LINEN | 0x00 << USART_CR2_STOP_Pos | ~USART_CR2_CLKEN | ~USART_CR2_CPOL | ~USART_CR2_CPHA | ~USART_CR2_LBCL | ~USART_CR2_LBDIE | \
		  ~USART_CR2_LBDL | 0x00 << USART_CR2_ADDM7_Pos | ~USART_CR2_DIS_NSS | ~USART_CR2_SLVEN; // 1 стоп, младшим байтом вперед, оверсемпл включен на 16 бит.*/
  USART3->CR3 = 0x00 << USART_CR3_TXFTCFG_Pos | 0x00 << USART_CR3_RXFTCFG_Pos /*| USART_CR3_DMAT | USART_CR3_DMAR*/; //
  USART3->PRESC = 0; // предделитель тактовой частоты. Частота на входе 120 МГц
  USART3->BRR = 521; // установка скорости расчетная формула. Хочу скорость 230400
  USART3->CR1 |= USART_CR1_UE; // включаем USART3

  while(1){
  USART3->TDR = 0xa5; // передаем данные в UART
  while(!USART3->ISR & USART_ISR_TC); // На ножке USART_TX сигнала нет.
  }

 

 

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


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

11 minutes ago, Alex_Golubev said:

GPIOD->MODER |= 0x2 << GPIO_MODER_MODE8_Pos; // перевод порта на альтернативную функцию в частности USART_TX GPIOD->MODER |= 0x2 << GPIO_MODER_MODE9_Pos; // перевод порта на альтернативную функцию в частности USART_RX

А вы уверены, что MODER содержал нули по указанной позиции? Если там было, например 0x01b, то двоечки уже не будет.

 

13 minutes ago, Alex_Golubev said:

GPIOD->AFR[1] |= 0x7 << GPIO_AFRH_AFSEL8_Pos | 0x7 << GPIO_AFRH_AFSEL9_Pos; // переключение мультиплексора на альтернативные выводы AF7

А где включаете клок для этих пинов?

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


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

8 минут назад, Alex_Golubev сказал:

Не могу запустить USART на stm32h743. Нет сигнала на выходе TX
Что сделал...

Ну, а разрешение работы приемника и передатчика где? Оно в CR1 должно быть.

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


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

15 minutes ago, Alex_Golubev said:

USART3->CR1 |= USART_CR1_UE; // включаем USART3

А приёмник и передатчик не включили?

1 minute ago, Arlleex said:

Ну, а разрешение работы приемника и передатчика где? Оно в CR1 должно быть.

Уважаемый @Arlleex опередил)

17 minutes ago, Alex_Golubev said:

SET_BIT(RCC->AHB4ENR, RCC_AHB4ENR_GPIODEN);

А, увидел, что пины включаете. Стиль кодирования у вас разный. Не сразу заметил.

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


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

23 minutes ago, Alex_Golubev said:

while(!USART3->ISR & USART_ISR_TC); // На ножке USART_TX сигнала нет

Доктора!!!!!!!!!!!!!

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


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

Разница между ! и ~ небольшаяю Или приоритеты операций изучать

 

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

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


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

11 минут назад, GenaSPB сказал:

Доктора!!!!!!!!!!!!!

А, кстати да - но я туда чего-то не посмотрел даже:this:

7 минут назад, GenaSPB сказал:

Разница между ! и ~ небольшая...

Тем не менее, оптимальнее все-таки через !.
Хотя при оптимизации, возможно, и не важно.

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


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

Там скорее всего просто забыты скобки: while (!(USART3->ISR & USART_ISR_TC));

 

А вот такое: GPIOD->MODER |= 0x2 << GPIO_MODER_MODE8_Pos;

И такое: GPIOD->OSPEEDR |= 0x2 << GPIO_OSPEEDR_OSPEED8_Pos;

и подобное - признаки типичного быдлокода. Раз делается операция "|=" то предполагается, что предыдущее содержимое регистров может быть !=0, но тогда результат будет ошибочный. А если предыдущее содержимое ==0 то зачем тогда |= ???

Это уже не говоря о том, что нет никакой заботы об атомарности модификации этих регистров. Если в соседней задаче РТОС (или ISR) завтра потребуется сконфигурить другие пины порта из того же регистра - начнутся очередные поиски и костыление багов.  :unknw:

Вроде очевидные вещи, но чайники повторяют и повторяют такое, таская друг у друга такие "шедевры".

 

А здесь: GPIOD->PUPDR &= 0x00 << GPIO_PUPDR_PUPD8_Pos; // отключение подтяжки

(и строкой ниже) решили подтяжки для всего порта сразу отключить. Видимо - чтобы два раза не бегать.  :biggrin:

Фиг с ним что там могут использоваться ещё и другие пины, в другом месте.

 

RCC->APB1LENR |= RCC_APB1LENR_USART3EN; // подключаем USART 3 к шине ABP1

А если не повезёт - то параллельно отключаем тактирование другой периферии. Ежли вдруг в это время другая задача захочет его включить.  :biggrin:

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


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

24 minutes ago, jcxz said:

Раз делается операция "|=" то предполагается, что предыдущее содержимое регистров может быть !=0, но тогда результат будет ошибочный.

Тут всё правильно, т.к. MODER включает в себя одинаковые группы битов для конфигруцаии пинов. И другие состояние мы трогать не имеем права. Другое дело, что перед такой операцией группу нужно обнулить, и наложить новую маску. Про атомарность операции согласен, сам так делаю. Хотя раньше грешил))

Вот фрагмент из либы управления пинами

            static void setAlternate( const Function func ) {
                TCritSect cs;
                auto &afr = base()->AFR[PinNum / 8];
                afr &= ~AFR_MASK;
                afr |= static_cast<uint32_t>(func) << AFR_SHIFT;
            }
            /* true sets aoutput as logic 1 and false sets it as logic 0*/
            static void set( const bool level ) {
                base()->BSRR = level ? SET_MASK : CLEAR_MASK; // здесь атомарность обеспечена железом
            }
            static void toggle() {
                TCritSect cs;
                base()->ODR ^= SET_MASK;
            }
            static void setModer( const Moder moder ) {
                TCritSect cs;
                base()->MODER &= ~MODER_MASK;
                base()->MODER  |= static_cast<uint8_t>(moder) << MODER_SHIFT;
            }

 

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


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

9 минут назад, haker_fox сказал:

Тут всё правильно, т.к. MODER включает в себя одинаковые группы битов для конфигруцаии пинов.

А что именно "правильно"? Если до этого был режим 0, станет 2, если был 1 - станет 3. Сомневаюсь, что автор хотел именно такого поведения. Полагаю что он хотел какой-то один определённый режим поставить.

 

9 минут назад, haker_fox сказал:

 


            static void toggle() {
                TCritSect cs;
                base()->ODR ^= SET_MASK;
            }

 

А здесь можно и без критической секции обойтись. Подумайте как.  :wink2:

Если конечно не переключаете один и тот же пин из разных задач.

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


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

1 час назад, Alex_Golubev сказал:

GPIOD->PUPDR &= 0x00 << GPIO_PUPDR_PUPD8_Pos; // отключение подтяжки

Здесь вы весь регистр обнулили, вместо одного бита.

Бит обнулять так:

GPIOD->PUPDR &= ~(1UL << GPIO_PUPDR_PUPD8_Pos);

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


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

Поправил код с вашей критикой. USART заработал. 

Добавил DMA ---> USART3. И не смог запустить. 

Скрытый текст

ExternalsBlocks_TX[0] = 0x85;

	RCC->APB1LENR |= RCC_APB1LENR_USART3EN; // подключаем USART 3 к шине ABP1
	while (!(RCC->APB1LENR & RCC_APB1LENR_USART3EN)); // ждем чтобы гарантированно подключилась
	MODIFY_REG(GPIOD->MODER, GPIO_MODER_MODE8, 0x2 << GPIO_MODER_MODE8_Pos); // перевод порта на альтернативную функцию в частности USART_TX
	MODIFY_REG(GPIOD->MODER, GPIO_MODER_MODE9, 0x2 << GPIO_MODER_MODE9_Pos); // перевод порта на альтернативную функцию в частности USART_RX
	MODIFY_REG(GPIOD->OSPEEDR, GPIO_OSPEEDR_OSPEED8,0x2 << GPIO_OSPEEDR_OSPEED8_Pos); // настройка скорости фронта USART скорость наибольшая
	MODIFY_REG(GPIOD->OSPEEDR, GPIO_OSPEEDR_OSPEED9,0x2 << GPIO_OSPEEDR_OSPEED9_Pos); // настройка скорости фронта USART скорость наибольшая
	MODIFY_REG(GPIOD->PUPDR, GPIO_PUPDR_PUPD8, 0x00 << GPIO_PUPDR_PUPD8_Pos); // отключение подтяжки
	MODIFY_REG(GPIOD->PUPDR, GPIO_PUPDR_PUPD9, 0x00 << GPIO_PUPDR_PUPD9_Pos); // отключение подтяжки
	MODIFY_REG(GPIOD->AFR[1], GPIO_AFRH_AFSEL8, 0x7 << GPIO_AFRH_AFSEL8_Pos); // переключение на альтернативный режим работы порта AF7
	MODIFY_REG(GPIOD->AFR[1], GPIO_AFRH_AFSEL9, 0x7 << GPIO_AFRH_AFSEL9_Pos); // переключение на альтернативный режим работы порта AF7

	MODIFY_REG(GPIOD->MODER, GPIO_MODER_MODE10, 0x1 << GPIO_MODER_MODE10_Pos); // перевод порта на выход RE
	MODIFY_REG(GPIOD->OSPEEDR,GPIO_OSPEEDR_OSPEED10,0x2 << GPIO_OSPEEDR_OSPEED10_Pos); // настройка скорости фронта для RE скорость наибольшая
	MODIFY_REG(GPIOD->PUPDR, GPIO_PUPDR_PUPD10, 0x00 << GPIO_PUPDR_PUPD10_Pos); // отключение подтяжки
	SET_BIT(GPIOD->BSRR, GPIO_BSRR_BR10); //установка логического нуля на линии RE

	USART3->CR1 &= ~USART_CR1_UE; // отключение USART 3 для настройки
	while (USART3->CR1 & USART_CR1_UE); // проверяем что бит включения USART3 сброшен
	USART3->CR2 = 0x00;
	USART3->CR3 = USART_CR3_DMAT | USART_CR3_DMAR; // включение DMA
	USART3->PRESC = 0; // предделитель тактовой частоты
	USART3->BRR = 521; // установка скорости расчетная формула 521
	USART3->CR1 |= USART_CR1_TE; // включение передатчика
	USART3->CR1 |= USART_CR1_RE; // включение приемника
	USART3->CR1 |= USART_CR1_UE; // включаем USART3
	while (!(USART3->CR1 & USART_CR1_UE)); // проверяем что бит включения USART3 установлен

	RCC->AHB1ENR |= RCC_AHB1LPENR_DMA1LPEN; // подключаем DMA1 к шине AHB1
	while (!(RCC->AHB1ENR & RCC_AHB1LPENR_DMA1LPEN)); // ждем гарантированого включения
	DMA1_Stream1->CR &= ~DMA_SxCR_EN; // выключаем DMA
	while (DMA1_Stream1->CR & DMA_SxCR_EN); // ждем чтобы гарантировано был отключен DMA
	DMA1_Stream1->CR = DMA_SxCR_MINC | DMA_SxCR_TCIE; // настройка ДМА для USART3 инкремент памяти, включение прерывания по завершению приема
	DMA1_Stream1->NDTR = 1; // количество данных для передачи с USART3 в ОЗУ буфер
	DMA1_Stream1->PAR = (uint32_t) &USART3->RDR; // адрес от куда брать данные
	DMA1_Stream1->M0AR = (uint32_t)&ExternalsBlocks_RX; // указываем адрес масива куда писать
	DMA1_Stream1->CR |= DMA_SxCR_EN; // включаем DMA
	while (!(DMA1_Stream1->CR & DMA_SxCR_EN)); // ждем гарантированого включения

	DMA1_Stream2->CR &= ~DMA_SxCR_EN; // выключаем DMA
	while (DMA1_Stream2->CR & DMA_SxCR_EN); // ждем чтобы гарантировано был отключен DMA
	DMA1_Stream2->CR = DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_CIRC; // настройка ДМА для USART3 инкремент памяти, передача из памяти ---> USART3
	DMA1_Stream2->NDTR = 1; // количество данных для передачи с USART3 в ОЗУ буфер
	DMA1_Stream2->PAR = (uint32_t) &USART3->TDR; // адрес от куда брать данные
	DMA1_Stream2->M0AR = (uint32_t)&ExternalsBlocks_TX; // указываем адрес масива куда писать
	DMA1_Stream2->CR |= DMA_SxCR_EN; // включаем DMA
	while (!(DMA1_Stream2->CR & DMA_SxCR_EN)); // ждем гарантированого включения

 

Добавил буферы:

Скрытый текст

__attribute__((section(".dma_buffer")))
 uint8_t ExternalsBlocks_TX[256]; 
__attribute__((section(".dma_buffer")))
 uint8_t ExternalsBlocks_RX[256]; 

 

Определил их в файле flash.id

Скрытый текст

  .dma_buffer : 
  { *(.dma_buffer) 
  } >RAM_D3

 

 

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

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


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

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

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

×
×
  • Создать...