Продолжение статьи
"SOFT UART X3".
Код из статьи иногда пропускал ошибки на длинных посылках.
Здесь рабочий, немного подправленный код для STM32F103C8T6 для среды CooCox.
Для STM32F030F4P6 SOFT UART незаменимая штука! Там всего 1 UART.
Тест «BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAB» — LED ON на букву "А" в посылке.
Код
// SOFT UART - STM32F103C8T6 - CooCox (1.05.2015, zz555)
// http://we.easyelectronics.ru/STM32/vcp-soft_uart_x3-modifikaciya-stm32vldiscovery.html
// Для STM32F030F4P6 незаменимая штука! Там всего 1 UART.
// Тест «BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAB» — LED ON на букву "А" в посылке
// 10 bit protocol: 1-start bit, 8-bit data, 1-stop bit (bps = timer_irq/3)
//
// Recive bytes:
// 1 - waiting flag_rx_rdy = 1
// 2 - read rx_buf[]
// 3 - flag_rx_rdy = 0, rx_byte_no = 0
//
// Transmit bytes:
// 1 - copy bytes to tx_buf[]
// 2 - run tx_uart(number of bytes in tx_buf);
//
// PA1 (IN) RX
// PC13 (OUT) LED
#include "stm32f10x.h"
void tx_uart(uint8_t bytes);
#define RX (GPIOA->IDR & GPIO_IDR_IDR1)==GPIO_IDR_IDR1 // PA1 IN RX
#define TX0 GPIOA->BSRR = GPIO_BSRR_BR0 // PA0 OUT TX OFF
#define TX1 GPIOA->BSRR = GPIO_BSRR_BS0 // PA0 OUT TX ON
#define PC13_0 GPIOC->BRR |= GPIO_ODR_ODR13 // PC13 OUT LED OFF
#define PC13_1 GPIOC->BSRR |= GPIO_ODR_ODR13 // PC13 OUT LED ON
#define PC13_N GPIOC->ODR^=GPIO_ODR_ODR13 // PC13 OUT LED INVERT
#define BUF_SIZE 256
uint8_t rx_buf[BUF_SIZE];
uint8_t tx_buf[BUF_SIZE];
uint8_t rx_byte;
uint8_t tx_byte;
uint8_t rx_byte_no;
uint8_t state_rx;
uint8_t state_tx;
uint8_t rx_counter;
uint8_t tx_counter;
uint8_t rx_counter_equ;
uint8_t rx_mask;
uint8_t tx_mask;
uint8_t bit_no_rx;
uint8_t bit_no_tx;
uint8_t flag_rx_rdy;
uint8_t flag_tx_rdy;
uint8_t err;
uint8_t i;
uint8_t k;
uint32_t TimingDelay;
void TIM2_IRQHandler(void) {
// RX
if (rx_byte_no>0) {
k++;
if (k>30) {k=0; flag_rx_rdy=1;}
}
if (flag_rx_rdy==0) {
if (state_rx>1) {k=0; rx_counter++;} else rx_counter=1;
if (rx_counter==rx_counter_equ) {
rx_counter=0;
switch (state_rx) {
case 1: // start bit
{
if (RX) {} else { // PA1 - RX
rx_byte=0; bit_no_rx=1; state_rx=2; rx_counter_equ=4;
}
break;
}
case 2: // data bits
{
if (RX) rx_mask=1; else rx_mask=0; // PA1 - RX
rx_byte >>= 1;
rx_mask <<= 7;
rx_byte |= rx_mask;
bit_no_rx++;
if (bit_no_rx==9) state_rx=3;
rx_counter_equ=3;
break;
}
case 3: // stop bit
{
if (RX) { // PA1 - RX
rx_buf[rx_byte_no]=rx_byte;
rx_byte_no++;
if (rx_byte_no==BUF_SIZE-1) rx_byte_no=0;
} else err=1;
state_rx=1;
rx_counter_equ=1;
break;
}
}
}
}
if (flag_tx_rdy==1) { // TX
tx_counter++;
if (tx_counter==3) {
tx_counter=0;
switch (state_tx) {
case 1: // start bit
{
TX0;
bit_no_tx=1;
state_tx=2;
break;
}
case 2: // data bits
{
tx_mask=tx_byte & 1;
tx_byte >>= 1;
if (tx_mask==0) TX0; else TX1;
bit_no_tx++;
if (bit_no_tx>8) state_tx=3;
break;
}
case 3: // stop bit
{
TX1;
flag_tx_rdy=0;
break;
}
}
}
}
TIM2->SR &= ~TIM_SR_UIF;
}
// Функция временной задержки в милисекундах
void Delay_ms(uint32_t nTime) {
TimingDelay = nTime*2400;
while (TimingDelay != 0) TimingDelay--;
}
void flash (void) {
err=0;
for(i=0; i<10; i++) {
PC13_0;
Delay_ms(10);
PC13_1;
Delay_ms(10);
}
}
void tx_uart(uint8_t bytes) {
uint8_t i;
tx_counter=0;
for (i=0; i<bytes; i++) {
while (flag_tx_rdy==1) {}
tx_byte=tx_buf[i];
state_tx=1;
flag_tx_rdy=1;
}
}
//================================================================================
void Init_STM() {
RCC->APB2ENR |= (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPCEN);
GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0 | GPIO_CRL_MODE1 | GPIO_CRL_CNF1);
GPIOA->CRL |= (GPIO_CRL_MODE0_0 | GPIO_CRL_CNF1_1); // PA0 (OUT) TX, PA1 (IN) RX
GPIOA->BSRR = GPIO_BSRR_BS1;
GPIOC->CRH |= GPIO_CRH_MODE13; // PC13 (OUT) LED
// Инициализация таймера TIM2
RCC->CFGR |= RCC_CFGR_HPRE_DIV2; // sys_clk/2 (36/2=18 MHz)
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // Разрешаем тактирование TIM2
TIM2->DIER |= TIM_DIER_UIE; // Update interrupt enable
TIM2->PSC = 625-1; // Предделитель частоты перед таймером (при 0 максимальная частота) (18000/625=28.8 KHz)
TIM2->ARR = 1; // До скольки считает таймер (28.8/3=9600 Hz)
TIM2->CR1 |= (TIM_CR1_CEN | TIM_CR1_ARPE); // Запускаем таймер
NVIC_EnableIRQ (TIM2_IRQn); // Разрешаем прерывания TIM2
}
//================================================================================
int main (void) {
Init_STM();
// Init_UART
state_rx=1;
rx_counter_equ=1;
rx_byte_no=0;
rx_byte_no=0;
flag_rx_rdy=0;
flag_tx_rdy=0;
TX1;
PC13_0;
Delay_ms(10); // Пауза 0,01 с
PC13_1;
while (1) {
if (flag_rx_rdy==1) {
if (err==1) flash();
for(i=0; i<rx_byte_no; i++) {
tx_buf[i]=rx_buf[i];
if (rx_buf[i]==65) PC13_0; // "A" - код 65
}
tx_uart(rx_byte_no);
Delay_ms(10);
PC13_1;
rx_byte_no=0;
flag_rx_rdy=0;
}
}
}
Сообщение отредактировал ave! - May 2 2015, 20:41