Рабочий код. Проверено в железе. Под CooCox.
Прием осуществляется в прерывании.
Этот код шпаргалка для разных случаев.
На моем STM32F4Discovery стоит внешний кварц 8 MHz, нужно изменить 2 значения в системных файлах для настройки частоты от внешнего кварца 8 MHz. По умолчанию там настроено на кварц 25 MHz. Из-за этого все примеры из интернета у меня были нерабочие.
#define PLL_M 8 // 149 cтр. cmsis_boot/system_stm32f4xx.c
#define HSE_VALUE ((uint32_t)8000000) // 92 стр. cmsis_boot/stm32f4xx.h
Код: Выделить всё
// STM32F4 UART
// Автор: vk.com/zz555 (11.08.2015)
// USART1 - TX=PA9(PB6), RX=PA10(PB7)
// USART2 - TX=PA2(PD5), RX=PA3(PD6)
// USART3 - TX=PB10(PD8), RX=PB11(PC11)
// UART4 - TX=PA0(PC10), RX=PA1(P11)
// UART5 - TX=PC12, RX=PD2
// USART6 - TX=PC7, RX=PC7
// При создании нового проекта в CooCox в Viev/Repository/Pepipherals поставить только 2 галочки:
// M4 CMSIS core
// CMSIS BOOT
// Нужно изменить 2 значения в системных файлах для настройки частоты от внешнего кварца 8 MHz
// #define PLL_M 8 // 149 cтр. cmsis_boot/system_stm32f4xx.c
// #define HSE_VALUE ((uint32_t)8000000) // 92 стр. cmsis_boot/stm32f4xx.h
#include "stm32f4xx.h"
// У Stm32f4Discovery есть 4 светодиода на выводах: PD12 (green), PD13 (orange), PD14 (red), PD15 (blue)
#define LED_ON GPIOD->BSRRL = GPIO_BSRR_BS_15 // PD15 LED ON (пишем в младшие 16 бит, чтобы включить)
#define LED_OFF GPIOD->BSRRH = GPIO_BSRR_BS_15 // PD15 LED OFF (пишем в старшие 16 бит, чтобы выключить)
uint32_t tim_delay;
uint8_t rx_status;
uint8_t rx_data;
uint8_t rx_bit;
uint8_t rx_buf[64];
// Обработчик прерывания системного таймера, прерывания каждую 1 ms
void SysTick_Handler(void) {
if (tim_delay != 0) tim_delay--;
}
// Функция временной задержки в милисекундах
void Delay_ms(uint32_t delay) {
tim_delay = delay;
while (tim_delay != 0) {
if (rx_status == 1) return;
}
}
// Прерывание по приему данных по USART
void USART1_IRQHandler(void) {
if ((USART1->SR & USART_SR_RXNE) != 0) { // Если пришло что-то от USART
rx_data = USART1->DR; // Считываем то что пришло в переменную
rx_buf[rx_bit]=rx_data; // Помещаем принятый байт в буфер
if (rx_bit != 64) rx_bit++; else rx_bit=0; // Наращиваем счётчик байтов буфера
if (rx_data == 0x0D) rx_status=1; // Если пришел конец посылки <CR><LF> 0x0D,0x0A (13,10)
}
}
// Функция отправляет байт в USART
void send_uart(uint_fast8_t data) {
while (!(USART1->SR & USART_SR_TC)); // Ждем пока бит TC в регистре SR станет 1
USART1->DR=data; // Отсылаем байт через UART
}
// Функция отправляет строку в USART
void send_str(char * string) {
uint8_t i=0;
while (string[i]) {
send_uart(string[i]);
i++;
}
send_uart('\r');
send_uart('\n');
}
// Инициализация stm
void stm_init(void) {
SystemInit();
SysTick_Config(168000); // Запуск прерываний на системном счетчике при частоте 168 MHz - 1ms
// Инициализация USART1
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
GPIOD->MODER |= GPIO_MODER_MODER15_0; // LED (pin out)
GPIOB->MODER |= (GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1); // USART1 (TX=PB6, RX=PB7)
GPIOB->AFR[0] |= 0x77000000;
USART1->BRR = 0x222E; // 9600
USART1->CR1 |= USART_CR1_TE; // Разрешить передатчик
USART1->CR1 |= USART_CR1_RE; // Разрешить приёмник
USART1->CR1 |= USART_CR1_UE; // Разрешить USART
USART1->CR1 |= USART_CR1_RXNEIE; // Разрешить прерывание по приему данных
NVIC_EnableIRQ (USART1_IRQn); // Разрешить прерывания от USART1
}
int main(void) {
stm_init(); // Инициализация stm
while (1) {
LED_ON;
Delay_ms(100); // Задержка 0.1 с
LED_OFF;
send_str("STM32F4");
rx_status=0;
rx_bit=0;
Delay_ms(1000); // Задержка 1 с
// Проверка принятой посылки по UART
if (rx_status == 1) {
if (rx_buf[0]=='5') {
rx_status=0;
rx_bit=0;
rx_buf[0]=0;
send_str("5 OK"); // Ответ "5 OK" при приеме цифры "5"
Delay_ms(1000); // Задержка 1 с
}
}
}
}

