單芯片解決方案,開啟全新體驗——W55MH32 高性能以太網單片機
W55MH32是WIZnet重磅推出的高性能以太網單片機,它為用戶帶來前所未有的集成化體驗。這顆芯片將強大的組件集于一身,具體來說,一顆W55MH32內置高性能Arm? Cortex-M3核心,其主頻最高可達216MHz;配備1024KB FLASH與96KB SRAM,滿足存儲與數據處理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP協議棧、內置MAC以及PHY,擁有獨立的32KB以太網收發緩存,可供8個獨立硬件socket使用。如此配置,真正實現了All-in-One解決方案,為開發者提供極大便利。
在封裝規格上,W55MH32 提供了兩種選擇:QFN100和QFN68。
W55MH32L采用QFN100封裝版本,尺寸為12x12mm,其資源豐富,專為各種復雜工控場景設計。它擁有66個GPIO、3個ADC、12通道DMA、17個定時器、2個I2C、5個串口、2個SPI接口(其中1個帶I2S接口復用)、1個CAN、1個USB2.0以及1個SDIO接口。如此豐富的外設資源,能夠輕松應對工業控制中多樣化的連接需求,無論是與各類傳感器、執行器的通信,還是對復雜工業協議的支持,都能游刃有余,成為復雜工控領域的理想選擇。 同系列還有QFN68封裝的W55MH32Q版本,該版本體積更小,僅為8x8mm,成本低,適合集成度高的網關模組等場景,軟件使用方法一致。更多信息和資料請進入http://www.w5500.com/網站或者私信獲取。
此外,本W55MH32支持硬件加密算法單元,WIZnet還推出TOE+SSL應用,涵蓋TCP SSL、HTTP SSL以及 MQTT SSL等,為網絡通信安全再添保障。
為助力開發者快速上手與深入開發,基于W55MH32L這顆芯片,WIZnet精心打造了配套開發板。開發板集成WIZ-Link芯片,借助一根USB C口數據線,就能輕松實現調試、下載以及串口打印日志等功能。開發板將所有外設全部引出,拓展功能也大幅提升,便于開發者全面評估芯片性能。
若您想獲取芯片和開發板的更多詳細信息,包括產品特性、技術參數以及價格等,歡迎訪問官方網頁:http://www.w5500.com/,我們期待與您共同探索W55MH32的無限可能。
第十五章 DMA
本章參考資料:《W55MH32中文參考手冊》DMA控制器章節。
學習本章時,配合《W55MH32中文參考手冊》DMA控制器章節一起閱讀,效果會更佳,特別是涉及到寄存器說明的部分。
1 DMA簡介
DMA(Direct Memory Access)—直接存儲器存取,是單片機的一個外設,它的主要功能是用來搬數據,但是不需要占用CPU, 即在傳輸數據的時候,CPU可以干其他的事情,好像是多線程一樣。數據傳輸支持從外設到存儲器或者存儲器到存儲器, 這里的存儲器可以是SRAM或者是FLASH。DMA控制器包含了DMA1和DMA2,其中DMA1有7個通道,DMA2有5個通道, 這里的通道可以理解為傳輸數據的一種管道。要注意的是DMA2只存在于大容量產品和互聯型產品中。
2 DMA功能框圖
DMA控制器獨立于內核,屬于一個單獨的外設,結構比較簡單,從編程的角度來看,我們只需掌握功能框圖中的三部分內容即可, 具體見下圖,DMA框圖 :DMA控制器的框圖:
2.1 DMA請求
如果外設要想通過DMA來傳輸數據,必須先給DMA控制器發送DMA請求,DMA收到請求信號之后,控制器會給外設一個應答信號, 當外設應答后且DMA控制器收到應答信號之后,就會啟動DMA的傳輸,直到傳輸完畢。
DMA有DMA1和DMA2兩個控制器,DMA1有7個通道,DMA2有5個通道,不同的DMA控制器的通道對應著不同的外設請求, 這決定了我們在軟件編程上該怎么設置,具體見DMA請求映像表:
外設 | 通道 1 | 通道 2 | 通道 3 | 通道 4 | 通道 5 | 通道 6 | 通道 7 |
ADC1 | ADC1 | ||||||
SPI/I2S | SPI1_RX | SPI1_TX | SPI/I2S2_RX | SPI/I2S2_TX | |||
USART | USART3_TX | USART3_RX | USART1_TX | USART1_RX | USART2_RX | USART2_TX | |
I2C | I2C2_TX | I2C2_RX | I2C1_TX | I2C1_RX | |||
TIM1 | TIM1_CH1 | TIM1_CH2 |
TIM1_TX4 TIM1_TRIG TIM1_COM |
TIM1_UP | TIM1_CH3 | ||
TIM2 | TIM2_CH3 | TIM2_UP | TIM2_CH1 |
TIM2_CH2 TIM2_CH4 |
|||
TIM3 | TIM3_CH3 |
TIM3_CH4 TIM3_UP |
TIM3_CH1 TIM3_TRIG |
||||
TIM4 | TIM4_CH1 | TIM4_CH2 | TIM4_CH3 | TIM4_UP |
外設 | 通道 1 | 通道 2 | 通道 3 | 通道 4 | 通道 5 |
ADC3?1? | ADC3 | ||||
SPI/I2S3 | SPI/I2S3_RX | SPI/I2S3_TX | |||
UART4 | UART4_RX | UART4_TX | |||
SDIO?1? | SDIO | ||||
TIM5 |
TIM5_CH4 TIM5_TRIG |
TIM5_CH3 TIM5_UP |
TIM5_CH2 | TIM5_CH1 | |
TIM6/DAC 通道 1 |
TIM6_UP/ DAC 通道 1 |
||||
TIM7/DAC 通道 2 |
TIM7_UP/ DAC 通道 2 |
||||
TIM8?1? |
TIM8_CH3 TIM8_UP |
TIM8_CH4 TIM8_TRIG TIM8_COM |
TIM8_CH1 | TIM8_CH2 |
其中ADC3、SDIO和TIM8的DMA請求只在大容量產品中存在,這個在具體項目時要注意。
2.2 通道
DMA具有12個獨立可編程的通道,其中DMA1有7個通道,DMA2有5個通道,每個通道對應不同的外設的DMA請求。 雖然每個通道可以接收多個外設的請求,但是同一時間只能接收一個,不能同時接收多個。
2.3 仲裁器
當發生多個DMA通道請求時,就意味著有先后響應處理的順序問題,這個就由仲裁器也管理。仲裁器管理DMA通道請求分為兩個階段。 第一階段屬于軟件階段,可以在DMA_CCRx寄存器中設置,有4個等級:非常高、高、中和低四個優先級。第二階段屬于硬件階段, 如果兩個或以上的DMA通道請求設置的優先級一樣,則他們優先級取決于通道編號,編號越低優先權越高,比如通道0高于通道1。 在大容量產品和互聯型產品中, DMA1控制器擁有高于DMA2控制器的優先級。
3 DMA數據配置
使用DMA,最核心就是配置要傳輸的數據,包括數據從哪里來,要到哪里去,傳輸的數據的單位是什么,要傳多少數據,是一次傳輸還是循環傳輸等等。
3.1DMA傳輸方向
我們知道DMA傳輸數據的方向有三個:從外設到存儲器,從存儲器到外設,從存儲器到存儲器。 具體的方向DMA_CCR位4 DIR配置:0表示從外設到存儲器,1表示從存儲器到外設。 這里面涉及到的外設地址由DMA_CPAR配置,存儲器地址由DMA_CMAR配置。
外設到存儲器
當我們使用從外設到存儲器傳輸時,以ADC采集為例。DMA外設寄存器的地址對應的就是ADC數據寄存器的地址, DMA存儲器的地址就是我們自定義的變量(用來接收存儲AD采集的數據)的地址。方向我們設置外設為源地址。
存儲器到外設
當我們使用從存儲器到外設傳輸時,以串口向電腦端發送數據為例。DMA外設寄存器的地址對應的就是串口數據寄存器的地址, DMA存儲器的地址就是我們自定義的變量(相當于一個緩沖區,用來存儲通過串口發送到電腦的數據)的地址。方向我們設置外設為目標地址。
存儲器到存儲器
當我們使用從存儲器到存儲器傳輸時,以內部FLASH向內部SRAM復制數據為例。 DMA外設寄存器的地址對應的就是內部FLASH(我們這里把內部FALSH當作一個外設來看)的地址, DMA存儲器的地址就是我們自定義的變量(相當于一個緩沖區,用來存儲來自內部FLASH的數據)的地址。 方向我們設置外設(即內部FLASH)為源地址。跟上面兩個不一樣的是,這里需要把DMA_CCR位14:MEM2MEM:存儲器到存儲器模式配置為1,啟動M2M模式。
3.2傳輸大小及單位
當我們配置好數據要從哪里來到哪里去之后,我們還需要知道我們要傳輸的數據是多少,數據的單位是什么。
以串口向電腦發送數據為例,我們可以一次性給電腦發送很多數據,具體多少由DMA_CNDTR配置, 這是一個32位的寄存器,一次最多只能傳輸65535個數據。
要想數據傳輸正確,源和目標地址存儲的數據寬度還必須一致,串口數據寄存器是8位的, 所以我們定義的要發送的數據也必須是8位。外設的數據寬度由DMA_CCRx的PSIZE[1:0]配置, 可以是8/16/32位,存儲器的數據寬度由DMA_CCRx的MSIZE[1:0]配置,可以是8/16/32位。
在DMA控制器的控制下,數據要想有條不紊的從一個地方搬到另外一個地方,還必須正確設置兩邊數據指針的增量模式。 外設的地址指針由DMA_CCRx的PINC配置,存儲器的地址指針由MINC配置。以串口向電腦發送數據為例,要發送的數據很多, 每發送完一個,那么存儲器的地址指針就應該加1,而串口數據寄存器只有一個, 那么外設的地址指針就固定不變。具體的數據指針的增量模式由實際情況決定。
3.3 傳輸完成時間
數據什么時候傳輸完成,我們可以通過查詢標志位或者通過中斷的方式來鑒別。每個DMA通道在DMA傳輸過半、 傳輸完成和傳輸錯誤時都會有相應的標志位,如果使能了該類型的中斷后,則會產生中斷。有關各個標志位的詳細描述請參考DMA中斷狀態寄存器DMA_ISR的詳細描述。
傳輸完成還分兩種模式,是一次傳輸還是循環傳輸,一次傳輸很好理解,即是傳輸一次之后就停止,要想再傳輸的話, 必須關斷DMA使能后再重新配置后才能繼續傳輸。循環傳輸則是一次傳輸完成之后又恢復第一次傳輸時的配置循環傳輸, 不斷的重復。具體的由DMA_CCRx寄存器的CIRC 循環模式位控制。
4 DMA初始化結構體詳解
標準庫函數對每個外設都建立了一個初始化結構體xxx_InitTypeDef(xxx為外設名稱),結構體成員用于設置外設工作參數, 并由標準庫函數xxx_Init()調用這些設定參數進入設置外設相應的寄存器,達到配置外設工作環境的目的。
結構體xxx_InitTypeDef和庫函數xxx_Init配合使用是標準庫精髓所在,理解了結構體xxx_InitTypeDef每個成員意義基本上就可以對該外設運用自如。 結構體xxx_InitTypeDef定義在W55MH32_xxx.h(后面xxx為外設名稱)文件中,庫函數xxx_Init定義在W55MH32_xxx.c文件中, 編程時我們可以結合這兩個文件內注釋使用。
DMA_ InitTypeDef初始化結構體
typedef struct { uint32_t DMA_PeripheralBaseAddr; // 外設地址 uint32_t DMA_MemoryBaseAddr; // 存儲器地址 uint32_t DMA_DIR; // 傳輸方向 uint32_t DMA_BufferSize; // 傳輸數目 uint32_t DMA_PeripheralInc; // 外設地址增量模式 uint32_t DMA_MemoryInc; // 存儲器地址增量模式 uint32_t DMA_PeripheralDataSize; // 外設數據寬度 uint32_t DMA_MemoryDataSize; // 存儲器數據寬度 uint32_t DMA_Mode; // 模式選擇 uint32_t DMA_Priority; // 通道優先級 uint32_t DMA_M2M; // 存儲器到存儲器模式 } DMA_InitTypeDef;
DMA_PeripheralBaseAddr: 外設地址,設定DMA_CPAR寄存器的值;一般設置為外設的數據寄存器地址,如果是存儲器到存儲器模式則設置為其中一個存儲器地址。
DMA_Memory0BaseAddr: 存儲器地址,設定DMA_CMAR寄存器值;一般設置為我們自定義存儲區的首地址。
DMA_DIR: 傳輸方向選擇,可選外設到存儲器、存儲器到外設。它設定DMA_CCR寄存器的DIR[1:0]位的值。這里并沒有存儲器到存儲器的方向選擇,當使用存儲器到存儲器時,只需要把其中一個存儲器當作外設使用即可。
DMA_BufferSize: 設定待傳輸數據數目,初始化設定DMA_CNDTR寄存器的值。
DMA_PeripheralInc: 如果配置為DMA_PeripheralInc_Enable,使能外設地址自動遞增功能,它設定DMA_CCR寄存器的PINC位的值;一般外設都是只有一個數據寄存器,所以一般不會使能該位。
DMA_MemoryInc: 如果配置為DMA_MemoryInc_Enable,使能存儲器地址自動遞增功能,它設定DMA_CCR寄存器的MINC位的值;我們自定義的存儲區一般都是存放多個數據的,所以要使能存儲器地址自動遞增功能。
DMA_PeripheralDataSize: 外設數據寬度,可選字節(8位)、半字(16位)和字(32位),它設定DMA_CCR寄存器的PSIZE[1:0]位的值。
DMA_MemoryDataSize: 存儲器數據寬度,可選字節(8位)、半字(16位)和字(32位),它設定DMA_CCR寄存器的MSIZE[1:0]位的值。當外設和存儲器之間傳數據時,兩邊的數據寬度應該設置為一致大小。
DMA_Mode:DMA傳輸模式選擇,可選一次傳輸或者循環傳輸,它設定DMA_CCR寄存器的CIRC位的值。例程我們的ADC采集是持續循環進行的,所以使用循環傳輸模式。
DMA_Priority: 軟件設置通道的優先級,有4個可選優先級分別為非常高、高、中和低,它設定DMA_CCR寄存器的PL[1:0]位的值。DMA通道優先級只有在多個DMA通道同時使用時才有意義,如果是單個通道,優先級可以隨便設置。
DMA_M2M: 存儲器到存儲器模式,使用存儲器到存儲器時用到,設定DMA_CCR的位14 MEN2MEN即可啟動存儲器到存儲器模式。
5 DMA存儲器到外設模式實驗
5.1 代碼分析
USART初始化
代碼清單:DMA-5 USART初始化
void UART_Configuration(uint32_t bound) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = bound; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART_TEST, &USART_InitStructure); USART_Cmd(USART_TEST, ENABLE); }
這段代碼定義了UART_Configuration函數用于配置 UART,它接收波特率作為參數。函數先初始化 GPIO 和 USART 配置結構體,接著使能 USART1 和 GPIOA 的時鐘。然后將 PA9 配置為復用推挽輸出作為 TX 引腳,PA10 配置為浮空輸入作為 RX 引腳。之后設置 USART 的波特率、數據位、停止位、校驗位、硬件流控制等參數,并使能接收和發送模式。最后初始化并使能 USART
串口DMA傳輸配置
代碼清單:DMA-6 USART1 發送請求DMA設置
void DMA_RecvConfiguration(void) { DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //USART1_RX DMA Config DMA_DeInit(DMA1_Channel5); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Buff; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = BUFFSIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel5, &DMA_InitStructure); DMA_Cmd(DMA1_Channel5, ENABLE); } void DMA_SendConfiguration(void) { DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //USART1_TX DMA Config DMA_DeInit(DMA1_Channel4); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Buff; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = BUFFSIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel4, &DMA_InitStructure); DMA_Cmd(DMA1_Channel4, ENABLE); }
代碼定義了兩個函數用于配置 DMA(直接內存訪問)的接收和發送功能。DMA_RecvConfiguration 函數配置了 USART1 的 DMA 接收功能,開啟了 DMA1 的時鐘,將 DMA1 通道 5 初始化為從 USART1 的數據寄存器接收數據到內存緩沖區 Buff,并設置了數據方向、緩沖區大小、數據增量模式、數據大小、工作模式、優先級等參數,最后使能該通道。DMA_SendConfiguration 函數則配置了 USART1 的 DMA 發送功能,同樣開啟 DMA1 時鐘,將 DMA1 通道 4 初始化為從內存緩沖區 Buff 發送數據到 USART1 的數據寄存器,設置了相似的參數后使能該通道。
主函數
代碼清單:DMA-7 存儲器到外設模式主函數
int main(void) { uint32_t i; RCC_ClocksTypeDef clocks; delay_init(); UART_Configuration(115200); RCC_GetClocksFreq(&clocks); printf("n"); printf("SYSCLK: %3.1fMhz, HCLK: %3.1fMhz, PCLK1: %3.1fMhz, PCLK2: %3.1fMhz, ADCCLK: %3.1fMhzn", (float)clocks.SYSCLK_Frequency / 1000000, (float)clocks.HCLK_Frequency / 1000000, (float)clocks.PCLK1_Frequency / 1000000, (float)clocks.PCLK2_Frequency / 1000000, (float)clocks.ADCCLK_Frequency / 1000000); printf("USART Asyn DMA Test.n"); while (1) { DMA_Cmd(DMA1_Channel4, DISABLE); USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); DMA_RecvConfiguration(); while (DMA_GetFlagStatus(DMA1_FLAG_TC5) == RESET); printf("USART Asyn DMA Recv Completen"); for (i = 0; i < BUFFSIZE; i++) { printf("%c ,", Buff[i]); } DMA_Cmd(DMA1_Channel5, DISABLE); USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); DMA_SendConfiguration(); while (DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET); printf("USART Asyn DMA Send Completen"); } }
這段代碼是一個 C 語言的 main 函數,主要實現了 USART(通用同步異步收發器)的異步 DMA(直接內存訪問)測試功能。具體步驟如下:
定義變量 i 和 clocks,i 用于循環計數,clocks 用于存儲時鐘頻率信息。
初始化延時函數,以 115200 的波特率配置 UART,獲取系統時鐘頻率并存儲在 clocks 中。
打印系統各時鐘頻率信息,包括 SYSCLK、HCLK、PCLK1、PCLK2 和 ADCCLK,同時輸出測試提示信息。
進入無限循環,在循環中交替進行接收和發送操作:
接收操作:先禁用 DMA1 通道 4,使能 USART1 的接收 DMA 請求,調用 DMA_RecvConfiguration 函數配置 DMA 接收,等待接收完成標志置位,打印接收完成信息并逐個輸出接收到的數據。
發送操作:禁用 DMA1 通道 5,使能 USART1 的發送 DMA 請求,調用DMA_SendConfiguration 函數配置 DMA 發送,等待發送完成標志置位,打印發送完成信息。
通過這種方式,不斷進行數據的接收和發送測試。
5.2 下載驗證
保證開發板相關硬件連接正確,在電腦端打開串口調試助手,把編譯好的程序下載到開發板。
WIZnet 是一家無晶圓廠半導體公司,成立于 1998 年。產品包括互聯網處理器 iMCU?,它采用 TOE(TCP/IP 卸載引擎)技術,基于獨特的專利全硬連線 TCP/IP。iMCU? 面向各種應用中的嵌入式互聯網設備。
WIZnet 在全球擁有 70 多家分銷商,在香港、韓國、美國設有辦事處,提供技術支持和產品營銷。
香港辦事處管理的區域包括:澳大利亞、印度、土耳其、亞洲(韓國和日本除外)。
-
單片機
+關注
關注
6065文章
44934瀏覽量
647628 -
控制器
+關注
關注
114文章
16998瀏覽量
183168 -
寄存器
+關注
關注
31文章
5425瀏覽量
123549 -
dma
+關注
關注
3文章
574瀏覽量
102416
發布評論請先 登錄
第十五章 DAC (上篇)

第十五章 DAC (下篇)

《DNK210使用指南 -CanMV版 V1.0》第十五章 按鍵中斷實驗
視頻詳解:上海尤老師verilog入門到實戰第十五課
基于RFID和MySQL實現小區門禁系統
「正點原子Linux連載」第十五章按鍵輸入試驗
第十五屆智能車入門淺談 精選資料分享
第十五講 組合邏輯電路的分析方法和設計方法

第十五屆智能車入門淺談

【正點原子FPGA連載】第三十五章高速AD/DA實驗 -摘自【正點原子】新起點之FPGA開發指南_V2.1

【正點原子FPGA連載】第十五章 窗口門狗(WWDG)實驗 -摘自【正點原子】新起點之FPGA開發指南_V2.1

深度參與,共話未來 —— 吹田電氣亮相第十五屆亞洲電源技術發展論壇

評論