Я пытаюсь написать свой собственный драйвер для USART_TX на ядерной плате STM32L476RG. Здесь таблица и справочное руководство .
Я использую Keil uVision 5 и я установил в диалоговом окне Управление:
- CMSIS> Core
- Устройство> Запуск
- Xtal = 16 МГц
Я хочу создать односимвольный передатчик. Согласно инструкции в гл. 40 стр. 1332 Я написал этот код:
// APB1 connects USART2
// The USART2 EN bit on APB1ENR1 is the 17th
// See alternate functions pins and label for USART2_TX! PA2 is the pin and AF7 (AFRL register) is the function to be set
#include "stm32l4xx.h" // Device header
#define MASK(x) ((uint32_t) (1<<(x)));
void USART2_Init(void);
void USART2_Wr(int ch);
void delayMs(int delay);
int main(void){
USART2_Init();
while(1){
USART2_Wr('A');
delayMs(100);
}
}
void USART2_Init(void){
RCC->APB1ENR1 |= MASK(17); // Enable USART2 on APB1
// we know that the pin that permits the USART2_TX is the PA2, so...
RCC->AHB2ENR |= MASK(0); // enable GPIOA
// Now, in GPIOA 2 put the AF7, which can be set by placing AF7=0111 in AFSEL2 (pin2 selected)
// AFR[0] refers to GPIOA_AFRL register
// Remember: each pin asks for 4 bits to define the alternate functions. see pg. 87
// of the datasheet
GPIOA->AFR[0] |= 0x700;
GPIOA->MODER &= ~MASK(4);// now ... we set the PA2 directly with moder as alternate function "10"
// USART Features -----------
//USART2->CR1 |=MASK(15); //OVER8=1
USART2->BRR = 0x683; //USARTDIV=16Mhz/9600?
//USART2->BRR = 0x1A1; //This one works!!!
USART2->CR1 |=MASK(0); //UE
USART2->CR1 |=MASK(3); //TE
}
void USART2_Wr(int ch){
//wait when TX buffer is empty
while(!(USART2->ISR & 0x80)) {} //when data is transfered in the register the ISR goes 0x80.
//then we lock the procedure in a while loop until it happens
USART2->TDR =(ch & 0xFF);
}
void delayMs(int delay){
int i;
for (; delay>0; delay--){
for (i=0; i<3195; i++);
}
}
Теперь проблема:
Система работает, но не правильно. Я имею в виду: если я использую RealTerm со скоростью 9600 бод, как настроено в 0x683 в USART_BRR reg, это показывает мне неверный символ, но , если я устанавливаю 2400 в качестве скорости передачи в реальном времени, это работает!
Для извлечения 0x683 в USART_BRR reg я сослался на Sec. 40.5.4 Генерация скорости передачи в бодах USART и говорит, что если OVER8 = 0, USARTDIV = BRR. В моем случае USARTDIV = 16 МГц / 9600 = 1667d = 683 ч.
Я думаю, что проблема заключается в этой строке кода:
USART2->BRR = 0x683; //USARTDIV=16Mhz/9600?
, потому что, если я заменю его на
USART2->BRR = 0x1A1; //USARTDIV=16Mhz/9600?
Система работает на скорости 9600 бод.
Что не так в моем коде или в понимании вычислений USARTDIV?
Заранее спасибо за вашу поддержку.
С уважением, GM