設置 | 登錄 | 註冊

作者共發了2篇帖子。

【程序】STM32通過DMA自動接收串口數據到數組中

1樓 巨大八爪鱼 2017-1-16 17:44
#include <stm32f10x.h>

#define _BV(n) (1 << (n))

uint8_t num[2] = {0, 0}; // 數碼管兩側顯示的數字
const uint8_t seg8[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
uint8_t buf[8]; // 存放所接收內容的數組

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

void ser_in(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 par_out(void)
{
    GPIOB->BRR = GPIO_BRR_BR8; // RCLK=>PB8
    GPIOB->BSRR = GPIO_BSRR_BS8;
}

void seg_scan(void)
{
    uint8_t i;
    uint8_t n = num[0];
    for (i = 0; i <= 2; i++)
    {
        ser_in(seg8[n % 10]);
        ser_in(_BV(i));
        par_out();
        delay();
        n /= 10;
    }
    
    n = num[1];
    for (i = 5; i <= 7; i++)
    {
        ser_in(seg8[n % 10]);
        ser_in(_BV(i));
        par_out();
        delay();
        n /= 10;
    }
}

int main(void)
{
    // 配置數碼管輸出端口
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
    GPIOB->CRL = 0x30000000; // PB7~9設為輸出
    GPIOB->CRH = 0x00000033;
    
    // 配置串口
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN;
    GPIOA->CRH = 0x000008b0; // PA9(TX)設為復用50MHz推輓輸出, PA10(RX)設為輸入
    GPIOA->BSRR = GPIO_BSRR_BS10; // PA10帶上拉輸入
    USART1->BRR = 0x1d4c; // 波特率9600
    USART1->CR1 |= USART_CR1_UE | USART_CR1_RE | USART_CR1_TE; // 打開串口, 允許發送和接收
    USART1->CR3 |= USART_CR3_DMAR;
    
    // 配置DMA
    // USART1接收通道是DMA1的通道5, 這個不可更改!
    RCC->AHBENR |= RCC_AHBENR_DMA1EN; // 開DMA1時鐘
    DMA1_Channel5->CNDTR = sizeof(buf); // 傳輸的數據量為buf數組的容量
    DMA1_Channel5->CPAR = (uint32_t)&USART1->DR; // 源地址為串口的DR寄存器
    DMA1_Channel5->CMAR = (uint32_t)buf; // 目的地址為buf數組
    DMA1_Channel5->CCR |= DMA_CCR5_EN | DMA_CCR5_TCIE | DMA_CCR5_CIRC | DMA_CCR5_MINC; // 打開DMA通道及其中斷, 開循環模式, 目的地址buf自動增加
    NVIC->ISER[DMA1_Channel5_IRQn / 32] |= _BV(DMA1_Channel5_IRQn % 32);
    
    while (1)
        seg_scan();
}

// DMA傳輸完畢中斷
void DMA1_Channel5_IRQHandler(void)
{
    DMA1->IFCR |= DMA_IFCR_CTCIF5;
    num[0] = buf[num[1] % 8]; // 根據次數除以8的餘數確定數碼管右側顯示哪個數據
    num[1]++; // 中斷次數
}
2樓 巨大八爪鱼 2017-1-16 17:51
【運行結果】
在串口調試助手中發送字符串「abcdefgh」(注意不要加回車符),第一次發送時數碼管左側顯示1,右側顯示第一個字符a的ASCII編碼值97。第二次2 - 98,第三次3 - 99,……,第八次8 ~ 104,第九次又回到1 ~ 97,以此類推。。。

內容轉換:

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