我一直在嘗試一段時間,通過USART將我的計算機的數據塊傳輸到STM32L100C-DISCO
。出於性能原因,這是使用DMA完成的。但是,到目前爲止,我還沒有得到它的工作。因爲我似乎無法弄清楚我可能做錯了什麼,所以我想我會在這裏問。STM32L1的直接存儲器訪問RX
我使用的是libopencm3,但不幸的是,他們其他優秀的repository of examples在STM32L1xxx
上似乎沒有包含一個用於DMA的DMA。雖然我提到common DMA header file中的配置選項,但我檢查了我涵蓋了所有的基礎。
當然,我所指的STM32L1xxx的參考手冊,其中提到了DMA1以下請求表,導致我相信頻道6是什麼,我需要使用..
因爲我不確定內存和外設的大小(例如USART2),所以我對這兩種方法的所有8位,16位和32位組合都有所不同,但無濟於事。
毫不費力;這是一個最小的工作(呃,不工作..)我試圖做的節選。我覺得我忽略了DMA配置中的某些東西,因爲USART本身工作正常。
在這一點上,任何感激。
這段代碼背後的想法基本上是循環直到緩衝區中的數據完全被替換,然後當它輸出時。從主持人,我發送了一千字節的高度可識別的數據,但我收回的只是格式錯誤的垃圾。它是寫的東西,但不是我打算寫它。
編輯:這裏是內存映射的圖片。 USART2_BASE
的計算結果爲0x4000 4400
,所以這似乎也是好的。
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include "libopencm3/stm32/usart.h"
#include <libopencm3/stm32/dma.h>
const int buflength = 1024;
uint8_t buffer[1024];
static void clock_setup(void)
{
rcc_clock_setup_pll(&clock_config[CLOCK_VRANGE1_HSI_PLL_32MHZ]);
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_GPIOAEN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
rcc_periph_clock_enable(RCC_DMA1);
}
static void gpio_setup(void)
{
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO3);
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2);
gpio_set_af(GPIOA, GPIO_AF7, GPIO3);
gpio_set_af(GPIOA, GPIO_AF7, GPIO2);
}
static void usart_setup(void)
{
usart_set_baudrate(USART2, 115200);
usart_set_databits(USART2, 8);
usart_set_stopbits(USART2, USART_STOPBITS_1);
usart_set_mode(USART2, USART_MODE_TX_RX);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
usart_enable(USART2);
}
static void dma_setup(void)
{
dma_channel_reset(DMA1, DMA_CHANNEL6);
dma_set_priority(DMA1, DMA_CHANNEL6, DMA_CCR_PL_VERY_HIGH);
dma_set_memory_size(DMA1, DMA_CHANNEL6, DMA_CCR_MSIZE_8BIT);
dma_set_peripheral_size(DMA1, DMA_CHANNEL6, DMA_CCR_PSIZE_8BIT);
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL6);
dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL6);
dma_enable_circular_mode(DMA1, DMA_CHANNEL6);
dma_set_read_from_peripheral(DMA1, DMA_CHANNEL6);
dma_disable_transfer_error_interrupt(DMA1, DMA_CHANNEL6);
dma_disable_half_transfer_interrupt(DMA1, DMA_CHANNEL6);
dma_disable_transfer_complete_interrupt(DMA1, DMA_CHANNEL6);
dma_set_peripheral_address(DMA1, DMA_CHANNEL6, (uint32_t) USART2_BASE);
dma_set_memory_address(DMA1, DMA_CHANNEL6, (uint32_t) buffer);
dma_set_number_of_data(DMA1, DMA_CHANNEL6, buflength);
dma_enable_channel(DMA1, DMA_CHANNEL6);
}
int main(void)
{
int i;
for (i = 0; i < buflength; i++) {
buffer[i] = 65;
}
clock_setup();
gpio_setup();
usart_setup();
dma_setup();
usart_enable_rx_dma(USART2);
char flag = 1;
while (flag) {
flag = 0;
for (i = 0; i < buflength; i++) {
if (buffer[i] == 65) {
flag = 1;
}
}
}
usart_disable_rx_dma(USART2);
for (i = 0; i < buflength; i++) {
usart_send_blocking(USART2, buffer[i]);
}
usart_send_blocking(USART2, '\n');
return 0;
}
只是一個想法:不是一個解決方案,但如果你可以計算RX需要多長時間,看看它是否與波特率(最小0.08秒)一致,可以顯示錯誤事件是否觸發DMA(一個假定波特率是正確的,因爲你有非DMA工作)。 –
我不確定我完全理解你的意思,但我試圖將雙方的波特率降低到9600,並沒有解決問題(或者給我提供有意義的輸出)。調用'usart_send_blocking'和'usart_recv_blocking'確實可以正常工作。 – Joost
添加; 9600被選爲在謹慎方面犯錯 - 我認爲這將是一個安全的下限。 – Joost