用DMA直接驅動GPIO,實現GPIO最高輸出速率

2021-06-29 06:45:51 字數 3891 閱讀 4471

先上圖:stm32f303晶元,72m的主頻

可以看到gpio的達到了14.4m的翻轉速率,

再來上**:

rcc_ahbperiphclockcmd(rcc_ahbperiph_gpioc, enable);

gpioc->moder |= 0x55555555;

gpioc->ospeedr |= 0xfffffff;

gpioc->pupdr |= 0x55555555; 

u32 gpio_data[4]= ;

dma_inittypedef          dma_initstructure;

tim_timebaseinittypedef  tim_timebasestructure;

nvic_inittypedef nvic_initstructure;

/* timx clock enable */

rcc_apb1periphclockcmd(rcc_apb1periph_tim4, enable); 

/* dmax clock enable */

rcc_ahbperiphclockcmd(rcc_ahbperiph_dma1, enable); 

dma_deinit(dma1_channel7); 

dma_initstructure.dma_peripheralbaseaddr = (uint32_t)(&(gpioc->bsrr));  

dma_initstructure.dma_memorybaseaddr = (uint32_t)gpio_data;

dma_initstructure.dma_dir = dma_dir_peripheraldst;  

dma_initstructure.dma_buffersize = 4;

dma_initstructure.dma_peripheralinc = dma_peripheralinc_disable;

dma_initstructure.dma_memoryinc = dma_memoryinc_enable;

dma_initstructure.dma_peripheraldatasize = dma_peripheraldatasize_word;

dma_initstructure.dma_memorydatasize = dma_memorydatasize_word;

dma_initstructure.dma_mode = dma_mode_circular;

dma_initstructure.dma_priority = dma_priority_veryhigh;

dma_initstructure.dma_m2m = dma_m2m_enable;  

dma_init(dma1_channel7, &dma_initstructure);

dma1_channel7->ccr |= dma_ccr_en;

用dma記憶體到記憶體的模式,直接把gpio_data的資料迴圈的搬到gpioc的bsrr暫存器上來控制gpioc上電平的翻轉,這樣使得gpio的速度達到了最快,輸出70ns的脈寬,這已經是達到了dma匯流排頻寬的極限,要想再提高速度的話,就得提高stm32晶元的主頻。

再來看用**來實現的話,gpio能達到多快的速度。

先是用庫函式來操作,在main函式的while迴圈來翻轉電平

while(1)

可以看到最快只能輸出320ns的脈寬電平,而且高低電平脈寬還不一樣,那是因為處理while(1)占用了cpu的時間導致的。

再來看用暫存器直接操作gpio

while(1)

可以看到,最小脈寬電平可以達到40ns,直接操作暫存器的速度明顯要到庫函式操作要快好多,低電平的時間要比高電平的時間長很多,同樣也是因為處理while的原因。

用cpu操作暫存器可以達到最快的電平翻轉,但是這樣cpu的資源全用在這上面,不能再做其實的操作。如果用dma的話,完全可以不占用cpu資源來達到更高速率的gpio翻轉速度。假如我們要根據自己的需求來產生我們所需要的時序,那要怎樣做。其實也很簡單,我們只要用定時器觸發dma搬一次資料到bsrr暫存器,然後再通過調整gpio_data陣列裡的資料,就可以來實現我們所要的時序。

下面的**就是通過這種方式來實現讓gpioc產生1us脈寬的時鐘,

rcc_ahbperiphclockcmd(rcc_ahbperiph_gpioc, enable);

gpioc->moder |= 0x55555555;

gpioc->ospeedr |= 0xfffffff;

gpioc->pupdr |= 0x55555555; 

u32 gpio_data[4]= ;

dma_inittypedef          dma_initstructure;

tim_timebaseinittypedef  tim_timebasestructure;

nvic_inittypedef nvic_initstructure;

/* timx clock enable */

rcc_apb1periphclockcmd(rcc_apb1periph_tim4, enable); 

/* dmax clock enable */

rcc_ahbperiphclockcmd(rcc_ahbperiph_dma1, enable); 

dma_deinit(dma1_channel7); 

dma_initstructure.dma_peripheralbaseaddr = (uint32_t)(&(gpioc->bsrr));  

dma_initstructure.dma_memorybaseaddr = (uint32_t)gpio_data;

dma_initstructure.dma_dir = dma_dir_peripheraldst;  

dma_initstructure.dma_buffersize = 4;

dma_initstructure.dma_peripheralinc = dma_peripheralinc_disable;

dma_initstructure.dma_memoryinc = dma_memoryinc_enable;

dma_initstructure.dma_peripheraldatasize = dma_peripheraldatasize_word;

dma_initstructure.dma_memorydatasize = dma_memorydatasize_word;

dma_initstructure.dma_mode = dma_mode_circular;

dma_initstructure.dma_priority = dma_priority_veryhigh;

dma_initstructure.dma_m2m = dma_m2m_disable;  

dma_init(dma1_channel7, &dma_initstructure);

tim_timebasestructure.tim_period = 72;          

tim_timebasestructure.tim_prescaler = 0x0;       

tim_timebasestructure.tim_clockdivision = 0x0;    

tim_timebasestructure.tim_countermode = tim_countermode_up;   

tim_timebaseinit(tim4, &tim_timebasestructure);

tim_dmacmd(tim4, tim_dma_update, enable);

tim_selectoutputtrigger(tim4,tim_trgosource_update);

tim_cmd(tim4, enable); 

dma1_channel7->ccr |= dma_ccr_en;

用DMA直接驅動GPIO,實現GPIO最高輸出速率

用dma直接驅動gpio,實現gpio最高輸出速率 先上圖 stm32f303晶元,72m的主頻 可以看到gpio的達到了14.4m的翻轉速率,再來上 rcc ahbperiphclockcmd rcc ahbperiph gpioc,enable gpioc moder 0x55555555 gp...

利用DMA實現取樣資料的直接搬運儲存

嘗試了下stm32的adc取樣,並利用dma實現取樣資料的直接搬運儲存,這樣就不用cpu去參與操作了。我這裡用了3路的adc通道,1路外部變阻器輸入,另外兩路是內部的溫度取樣和vrefint,這樣就能組成連續的取樣,來測試多通道adc自動掃瞄了,adc分規則轉換和注入轉換,其實規則轉換就是按照既定的...

直接用socket實現HTTP協議

直接用socket實現http協議 這個網頁 那麼請求頭的寫法如下 第2行 主機名,格式為 host 主機 在這個例子中是 host www.sina.com.cn 第4行 指定瀏覽器的型別 有些伺服器會根據客戶伺服器種類的不同會增加或減少一些內容,在這個例子中可以這樣寫 user agent mo...