設置 | 登錄 | 註冊

作者共發了4篇帖子。

【C++程序】用C++編寫STM32F103串口通訊程序

1樓 巨大八爪鱼 2017-1-16 14:07

【程序運行效果】

2樓 巨大八爪鱼 2017-1-16 14:08
【程序】
#include <stm32f10x.h>

inline uint32_t _BV(uint8_t n)
{
    return (1 << n);
}

// 數碼管掃描類
class Scanner
{
private:
    static const uint8_t table[]; // 數碼管字形表
    void input(uint8_t data); // 74HC595串行輸入
    void output(void); // 74HC595並行輸出
public:
    Scanner(void); // 初始化GPIO口
    void delay(void);
    void display(uint16_t num, uint8_t start = 0, uint8_t len = 3, bool dot = false); // 動態掃描數碼管, 顯示len位數字num, 個位位於start處的數碼管
    void displayAt(uint8_t pos, uint8_t num, bool dot = false, bool delay = true); // 在指定數碼管上顯示指定數字
};

const uint8_t Scanner::table[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};

Scanner::Scanner(void)
{
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
    GPIOB->CRL = 0x30000000; // PB7~9設為輸出
    GPIOB->CRH = 0x00000033;
}

void Scanner::delay(void)
{
    uint16_t i;
    for (i = 0; i < 20000; i++);
}

void Scanner::input(uint8_t data)
{
    uint8_t i;
    for (i = 0; i < 8; i++)
    {
        GPIOB->BRR = GPIO_BRR_BR9; // SCLK=>PB9
        if (data & 0x80)
            GPIOB->BSRR = GPIO_BSRR_BS7; // DIO=>PB7
        else
            GPIOB->BRR = GPIO_BRR_BR7;
        data <<= 1;
        GPIOB->BSRR = GPIO_BSRR_BS9;
    }
}

void Scanner::output(void)
{
    GPIOB->BRR = GPIO_BRR_BR8; // RCLK=>PB8
    GPIOB->BSRR = GPIO_BSRR_BS8;
}

void Scanner::display(uint16_t num, uint8_t start, uint8_t len, bool dot)
{
    // 掃描方向是從右到左
    uint8_t i;
    for (i = 0; i < len; i++)
    {
        displayAt(start + i, num % 10, dot && i == 0);
        num /= 10;
    }
}

void Scanner::displayAt(uint8_t pos, uint8_t num, bool dot, bool delay)
{
    if (dot)
        input(table[num] & 0x7f);
    else
        input(table[num]);
    input(_BV(pos));
    output();
    if (delay)
        this->delay();
}

// 串口通信類
class CommPort : public Scanner
{
private:
    uint8_t num;
    uint8_t seconds;
public:
    CommPort(void);
    void run(void);
    void sendString(const char *s); // 串口發送字符串
    void setNum(uint8_t num);
    void timeUp(void);
};

CommPort::CommPort(void) : num(0), seconds(0)
{
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN;
    GPIOA->CRH = 0x000008b0; // PA9(TX)設為復用50MHz推輓輸出, PA10(RX)設為輸入
    GPIOA->BSRR = GPIO_BSRR_BS10; // PA10帶上拉輸入
    
    // 波特率9600=72MHz/16x, x=468.75
    // 468=0x1d4, 0.75=12/16, 12=0xc
    USART1->BRR = 0x1d4c;
    
    USART1->CR1 |= USART_CR1_UE | USART_CR1_RE | USART_CR1_TE | USART_CR1_RXNEIE; // 打開串口, 允許發送和接收, 開接收中斷
    NVIC->ISER[USART1_IRQn / 32] |= _BV(USART1_IRQn % 32);
    
    // 配置定時器
    RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
    TIM1->ARR = 9999;
    TIM1->PSC = 7199;
    TIM1->DIER |= TIM_DIER_UIE;
    NVIC->ISER[TIM1_UP_IRQn / 32] |= _BV(TIM1_UP_IRQn % 32); // 開定時器溢出中斷
    TIM1->CR1 |= TIM_CR1_URS;
    TIM1->EGR |= TIM_EGR_UG;
    TIM1->CR1 &= ~TIM_CR1_URS;
    TIM1->CR1 |= TIM_CR1_CEN;
}

void CommPort::run(void)
{
    sendString("\nHello World!\nTimer: ");
    while (1)
    {
        display(num);
        display(seconds, 6, 2, true); // 秒數(兩位)
        displayAt(5, TIM1->CNT % 10000 / 1000); // 毫秒數
    }
}

void CommPort::sendString(const char *s)
{
    while (*s)
    {
        while ((USART1->SR & USART_SR_TC) == 0);
        USART1->DR = *s++;
    }
}

void CommPort::setNum(uint8_t num)
{
    this->num = num;
}

void CommPort::timeUp(void)
{
    seconds++;
    if (seconds >= 100)
        seconds = 0;
    
    USART1->DR = '0' + seconds % 10;
}

CommPort *pCp; // 供中斷函數用的指針

int main(void)
{
    CommPort cp; // 兩個類的構造函數都要執行
    pCp = &cp;
    cp.run();
    return 0;
}

// 注意在C++程序中中斷函數要加前綴
extern "C" void TIM1_UP_IRQHandler(void)
{
    // 定時器溢出中斷
    TIM1->SR &= ~TIM_SR_UIF;
    pCp->timeUp();
}

extern "C" void USART1_IRQHandler(void)
{
    // 串口接收中斷
    if (USART1->SR & USART_SR_RXNE)
        pCp->setNum(USART1->DR);
}
3樓 巨大八爪鱼 2017-1-16 14:14

本人在測試此程序時,為了方便起見,PA9,PA10上是接的藍牙串口模塊。

4樓 巨大八爪鱼 2017-1-16 14:24
不過呢,51單片機沒法用C++編寫程序。因為編譯的時候Keil uVision5直接就失去了響應:

內容轉換:

回覆帖子
內容:
用戶名: 您目前是匿名發表。
驗證碼:
看不清?換一張
©2010-2025 Purasbar Ver3.0 [手機版] [桌面版]
除非另有聲明,本站採用知識共享署名-相同方式共享 3.0 Unported許可協議進行許可。