реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Soft UART, рабочий код
ave!
сообщение May 2 2015, 20:37
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 20-05-11
Пользователь №: 65 166



Продолжение статьи "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
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 16:55
Рейтинг@Mail.ru


Страница сгенерированна за 0.01373 секунд с 7
ELECTRONIX ©2004-2016