首頁(yè) > 評(píng)測(cè) > 帶你一起玩轉(zhuǎn)WPI基于靈動(dòng)MM32F0140 Arduino平臺(tái)方案開(kāi)發(fā)板

帶你一起玩轉(zhuǎn)WPI基于靈動(dòng)MM32F0140 Arduino平臺(tái)方案開(kāi)發(fā)板

  
  • 作者:
  • 來(lái)源:21ic BBS
  • [導(dǎo)讀]
  • 相遇疫情期間,無(wú)意中在大大通平臺(tái)上看到了大聯(lián)大世平集團(tuán)推出的基于靈動(dòng)微MM32F0140 MCU制作的Arduino平臺(tái)方案,在直播中了解到MM32F0410系列MCU功能特性,以及WPI詳細(xì)介紹了開(kāi)發(fā)的設(shè)

 

相遇
疫情期間,無(wú)意中在大大通平臺(tái)上看到了大聯(lián)大世平集團(tuán)推出的基于靈動(dòng)微MM32F0140 MCU制作的Arduino平臺(tái)方案,在直播中了解到MM32F0410系列MCU功能特性,以及WPI詳細(xì)介紹了開(kāi)發(fā)的設(shè)計(jì)、功能和特點(diǎn),對(duì)網(wǎng)友的很多提問(wèn)也都進(jìn)行了答復(fù)。活動(dòng)結(jié)束后有幸獲得了一塊開(kāi)發(fā)板,通過(guò)這幾天的研究和把玩,今天來(lái)帶大家一起玩轉(zhuǎn)這塊開(kāi)發(fā)板,在程序設(shè)計(jì)的過(guò)程中有不少的注意點(diǎn)和優(yōu)化設(shè)計(jì)分享給大家哦。有興趣的小伙伴可以去觀看直播回放哈:https://www.wpgdadatong.com/webinar/243499494

MM32F0140主要特點(diǎn)
  • Arm Cortex-M0內(nèi)核,運(yùn)行頻率高達(dá)72MHz
  • 最高64KB FLASH和8KB SRAM
  • 內(nèi)置5個(gè)DMA通道
  • 內(nèi)置32-bit硬件除法單元
  • 3組UART、2組SPI、2組I2C、1組I2C
  • 1組FlexCAN,支持CAN2.0協(xié)議
  • 1組高級(jí)定時(shí)器,可輸出4通道帶互補(bǔ)的PWM波形,支持死區(qū)和剎車功能
  • 1組32-bit定時(shí)器、4組16-bit定時(shí)器
  • 1組12-bit SAR ADC,最高支持1Msps采樣率和13路采樣通道
  • 1組高速模擬比較單元
  • 2.0V~5.5V寬工作電壓

MM32F0140資源圖

開(kāi)發(fā)板功能示意圖

開(kāi)發(fā)板實(shí)物展示圖

開(kāi)發(fā)板功能介紹
大聯(lián)大世平集團(tuán)推出的基于靈動(dòng)微MM32F0140系列MCU制作的Arduino平臺(tái)方案開(kāi)發(fā)板,搭配了眾多的傳感器件以及接口IC,例如ams TMF8821多點(diǎn)ToF、Novosense的NSHT35溫濕傳感器和NCA1042 CAN收發(fā)器、Vishay的TFDU4300紅外收發(fā)器等等,另外還有onsemi的CAT24C03 EEPROM、Winbond的W25Q16JV SPI FLASH、LCD接口、按鍵、RGB LED等等……另外還兼容Arduino接口,方便更多的擴(kuò)展與應(yīng)用。通過(guò)這塊開(kāi)發(fā)板,我們可以實(shí)現(xiàn)如下功能:
  • 實(shí)現(xiàn)ADC采樣
  • 實(shí)現(xiàn)按鍵檢測(cè)
  • 實(shí)現(xiàn)FlexCAN通訊
  • 實(shí)現(xiàn)EEPROM數(shù)據(jù)存取功能
  • 實(shí)現(xiàn)DAC音頻播放功能
  • 實(shí)現(xiàn)IrDA紅外通訊功能
  • 實(shí)現(xiàn)LCD TFT液晶屏幕顯示
  • 實(shí)現(xiàn)NSHT35溫濕檢測(cè)功能
  • 實(shí)現(xiàn)RGB LED控制功能
  • 實(shí)現(xiàn)SWITCH開(kāi)關(guān)狀態(tài)檢測(cè)功能
  • 實(shí)現(xiàn)ToF高精度測(cè)距功能
  • 實(shí)現(xiàn)SPI FLASH數(shù)據(jù)存取功能
  • 實(shí)現(xiàn)Xmodem下載文件/數(shù)據(jù)到SPI FLASH的應(yīng)用功能

需要說(shuō)明的是在收到的開(kāi)發(fā)上NSHT35溫濕度傳感器屬于選焊器件,沒(méi)有焊接在板子上;另外ToF高精度測(cè)距模塊使用的TFM8821,對(duì)于它的操作需要原廠的技術(shù)支持并提供相應(yīng)的參數(shù)文件;所以這兩塊功能作為保留,暫時(shí)無(wú)法進(jìn)行操作和實(shí)現(xiàn);而我們會(huì)將開(kāi)發(fā)板上其余所有功能都一一實(shí)現(xiàn),并進(jìn)行演示和測(cè)試。

大大通上提供部分技術(shù)文檔的下載:https://www.wpgdadatong.com/solution/detail?PID=5481,其中包含原理圖、項(xiàng)目計(jì)劃表、硬件BOM、以及硬件PCB圖;但沒(méi)有提供開(kāi)發(fā)板的軟件工程源代碼,以及其它的一些手冊(cè)資料也都沒(méi)有開(kāi)放出來(lái),這讓很多小伙伴在拿到這個(gè)開(kāi)發(fā)板后,都只能看看原理圖、看看開(kāi)發(fā)板……要怎么去調(diào)試、演示成了最大的問(wèn)題。下面我們一邊分析硬件原理圖,一邊演示開(kāi)發(fā)板功能,來(lái)實(shí)現(xiàn)上面提到的實(shí)現(xiàn)功能,分享給大家。

原理圖設(shè)計(jì)

原理圖的解讀和建議
整個(gè)開(kāi)發(fā)板由一個(gè)Micro USB接口供電,這個(gè)Micro USB僅為供電接口,不帶有任何通訊調(diào)試功能哈;所以個(gè)人建議在下次改板時(shí),USB接口可以加一個(gè)CH340,作為調(diào)試用,會(huì)很實(shí)用,也會(huì)很方便!

開(kāi)發(fā)板上MM32F0140芯片的程序下載接口為1.27mm間距的2*5雙排針,可能是為了節(jié)省PCB的空間吧,才使用了這們的接口;同樣是通過(guò)SWD接口下載程序,我更喜歡4PIN(VCC、GND、SWDIO、SWDCLK)或者5PIN(VCC、GND、SWDIO、SWDCLK、NRST)這樣的2.54間距排針,這樣可以直接插上杜邦線就可以下載程序了,但現(xiàn)在板子上這樣的接口,我還需要另外配一個(gè)2.54mm間距的2*10 接口轉(zhuǎn)1.27mm間距的2*5接口的轉(zhuǎn)接板,不是很方便。

整個(gè)硬件系統(tǒng)可以工作在5V電壓下,也可以工作在3.3V電壓下,可以通過(guò)JP1接口進(jìn)行跳帽選擇;但需要注意的是開(kāi)發(fā)上的SPI FLASH和LCD都只能是3.3V供電的,所以在5V供電時(shí),需要將這些元器件的連接斷開(kāi)。

官網(wǎng)上下載下來(lái)的原理圖中關(guān)于RGB LED設(shè)計(jì)部分有錯(cuò)誤,原理圖中設(shè)計(jì)通過(guò)JP3、JP4、JP5這3個(gè)跳帽將RGB LED的3個(gè)控制引腳分為與PA2、PA1、PA3進(jìn)行連接,但在實(shí)際收到的開(kāi)發(fā)板上,這3個(gè)跳帽連接的是PB1、PA1、PB0這3個(gè)端口引腳,應(yīng)該是為了避免端口功能重復(fù)使用,更新的原理圖沒(méi)有同步過(guò)來(lái),這個(gè)在程序設(shè)計(jì)的時(shí)候,需要注意一下。

CAN通訊的收發(fā)芯片使用的是NCA1042,這個(gè)芯片的工作電壓是5V,所以開(kāi)發(fā)板在測(cè)試CAN功能時(shí),一定要有5V電源輸入;另外需要注意的是原理圖中使用了PA8這個(gè)引腳來(lái)控制NCA1042的工作狀態(tài),需要將PA8置為低電平時(shí),NCA1042才能夠正常工作,如果PA8為高電平,那NCA1042則為待機(jī)狀態(tài),此時(shí)CAN收發(fā)器是不工作的,更沒(méi)有數(shù)據(jù)傳輸,更有甚者在CAN上位機(jī)軟件發(fā)送數(shù)據(jù)時(shí),還會(huì)提示發(fā)送失敗,這些需要注意。

在測(cè)試IrDA通訊時(shí),需要通過(guò)JP8將TFDU4300的SD與GND相連接,這樣IrDA才會(huì)處于正常工作的狀態(tài);另外就是TFDU4300收發(fā)數(shù)據(jù)是半雙工的,即同一時(shí)刻只能發(fā)送數(shù)據(jù)或者接收數(shù)據(jù),更達(dá)不到自發(fā)自收的功能,所以需要借助我們之前做的IrDA開(kāi)發(fā)板來(lái)搭配測(cè)試。

開(kāi)發(fā)平臺(tái)環(huán)境
硬件包含:MM32F0140 Arduino開(kāi)發(fā)板、ARM仿真器、USB轉(zhuǎn)TTL調(diào)試工具、JTAG 20PIN轉(zhuǎn)10PIN轉(zhuǎn)換板、LCD TFT液晶顯示屏、以及用于播放音樂(lè)用的音箱。
軟件包含:Keil MDK集成開(kāi)發(fā)環(huán)境、SecureCRT調(diào)試終端、Image2Lcd圖片數(shù)據(jù)提取軟件等。


RGB LED控制
使用GPIO的控制方式,循環(huán)讓3個(gè)LED點(diǎn)亮,如果需要實(shí)現(xiàn)RGB呼吸燈效果,可以參考之前【MM32+模塊】專題帖,實(shí)現(xiàn)代碼和測(cè)試效果如下:
  1. void RGBLED_Toggle(void)
  2. {
  3.     static uint8_t Step = 0;
  4.  
  5.     switch(Step)
  6.     {
  7.         case 0:
  8.             GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_RESET);
  9.             GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET);
  10.             GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_SET);
  11.             break;
  12.  
  13.         case 1:
  14.             GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_SET);
  15.             GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET);
  16.             GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_SET);
  17.             break;
  18.  
  19.         case 2:
  20.             GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_SET);
  21.             GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET);
  22.             GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_RESET);
  23.             break;
  24.  
  25.         default:
  26.             break;
  27.     }
  28.  
  29.     Step = (Step + 1) % 3;
  30. }
復(fù)制代碼

獨(dú)立按鍵檢測(cè)
通過(guò)時(shí)間片輪轉(zhuǎn)調(diào)度的方式,軟件延時(shí)去抖處理,實(shí)現(xiàn)了4個(gè)按鍵的獨(dú)立檢測(cè),實(shí)現(xiàn)代碼和測(cè)試效果如下:
  1. void BUTTON_SubScan(uint8_t *State, uint8_t *Count, uint8_t Value, char *Name)
  2. {
  3.     if(*State == 0)
  4.     {
  5.         if(Value == Bit_RESET) *Count += 1;
  6.         else                   *Count  = 0;
  7.  
  8.         if(*Count > 5)
  9.         {
  10.             *Count = 0; *State = 1;
  11.             printf("\r\n%s Pressed", Name);
  12.         }
  13.     }
  14.     else
  15.     {
  16.         if(Value != Bit_RESET) *Count += 1;
  17.         else                   *Count  = 0;
  18.  
  19.         if(*Count > 5)
  20.         {
  21.             *Count = 0; *State = 0;
  22.             printf("\r\n%s Release", Name);
  23.         }
  24.     }
  25. }
  26.  
  27. void BUTTON_Scan(void)
  28. {
  29.     static uint8_t State[4] = {0, 0, 0, 0};
  30.     static uint8_t Count[4] = {0, 0, 0, 0};
  31.  
  32.     BUTTON_SubScan(&State[0], &Count[0], GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0), "SW2");
  33.     BUTTON_SubScan(&State[1], &Count[1], GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_2), "SW3");
  34.     BUTTON_SubScan(&State[2], &Count[2], GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_3), "SW4");
  35.     BUTTON_SubScan(&State[3], &Count[3], GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_2), "SW5");
  36. }
復(fù)制代碼

SWITCH開(kāi)關(guān)狀態(tài)檢測(cè)
SWITCH是一個(gè)4位的撥碼開(kāi)關(guān),通過(guò)GPIO端口引腳的狀態(tài)位來(lái)判斷撥碼開(kāi)關(guān)所處的狀態(tài),實(shí)現(xiàn)代碼和測(cè)試效果如下:
  1. void SWITCH_SubScan(uint8_t *State, uint8_t *Count, uint8_t Value, char *Name)
  2. {
  3.     if(*State == 0)
  4.     {
  5.         if(Value != Bit_RESET) *Count += 1;
  6.         else                   *Count  = 0;
  7.  
  8.         if(*Count > 5)
  9.         {
  10.             *Count = 0; *State = 1;
  11.             printf("\r\n%s -> OFF", Name);
  12.         }
  13.     }
  14.     else
  15.     {
  16.         if(Value == Bit_RESET) *Count += 1;
  17.         else                   *Count  = 0;
  18.  
  19.         if(*Count > 5)
  20.         {
  21.             *Count = 0; *State = 0;
  22.             printf("\r\n%s -> ON ", Name);
  23.         }
  24.     }
  25. }
  26.  
  27. void SWITCH_Scan(void)
  28. {
  29.     static uint8_t State[4] = {0, 0, 0, 0};
  30.     static uint8_t Count[4] = {0, 0, 0, 0};
  31.  
  32.     SWITCH_SubScan(&State[0], &Count[0], GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15), "SW1-1");
  33.     SWITCH_SubScan(&State[1], &Count[1], GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_15), "SW1-2");
  34.     SWITCH_SubScan(&State[2], &Count[2], GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_14), "SW1-3");
  35.     SWITCH_SubScan(&State[3], &Count[3], GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13), "SW1-4");
  36. }
復(fù)制代碼

ADC采樣
ADC包含了實(shí)現(xiàn)掉電壓檢測(cè)功能和可調(diào)電位器的電壓檢測(cè)這兩個(gè)功能,采用的單通道獨(dú)立查詢采樣的實(shí)現(xiàn)方式,實(shí)現(xiàn)代碼和測(cè)試效果如下:
  1. void ADC_Handler(void)
  2. {
  3.     uint16_t Result  = 0;
  4.     float    Voltage = 0.0;
  5.  
  6.     Result = ADC_Convert(ADC_Channel_10);
  7.  
  8.     Voltage = (float)Result / 4096 * 3.3;
  9.  
  10.     printf("\r\n");
  11.     printf("\r\nPB3 <-> ADC1_CH10 : %0.3fV", Voltage);
  12.  
  13.     Result = ADC_Convert(ADC_Channel_12);
  14.  
  15.     Voltage = (float)Result / 4096 * 3.3;
  16.  
  17.     printf("\r\nPB7 <-> ADC1_CH12 : %0.3fV", Voltage);
  18.     printf("\r\n");
  19. }
復(fù)制代碼

FlexCAN通訊
FlexCAN默認(rèn)配置為500kbps的通訊速率,每間隔3秒中向CAN總線中發(fā)送一個(gè)報(bào)文;配置了一個(gè)接收郵箱,采用中斷的方式,在接收到數(shù)據(jù)后通過(guò)調(diào)試終端軟件打印顯示出來(lái),實(shí)現(xiàn)代碼和測(cè)試效果如下:
  1. void FLEX_CAN_IRQHandler(void)
  2. {
  3.     flexcan_frame_t flexcan_frame_rx;
  4.  
  5.     if(0U != FLEXCAN_GetMbStatusFlags(FLEX_CAN1, 1 << RX_MESSAGE_BUFFER_NUM))
  6.     {
  7.         FLEXCAN_ClearMbStatusFlags(FLEX_CAN1, 1 << RX_MESSAGE_BUFFER_NUM);
  8.  
  9.         FLEXCAN_ReadRxMb(FLEX_CAN1, RX_MESSAGE_BUFFER_NUM, &flexcan_frame_rx);
  10.  
  11.         printf("\r\nReceived message from MB%d", RX_MESSAGE_BUFFER_NUM);
  12.  
  13.         printf("\r\n");
  14.         printf("\r\nrx form  = 0x%x", (flexcan_frame_rx.id & CAN_ID_STD_MASK) >> CAN_ID_STD_SHIFT);
  15.         printf("\r\nrx word0 = 0x%x", flexcan_frame_rx.dataWord0);
  16.         printf("\r\nrx word1 = 0x%x", flexcan_frame_rx.dataWord1);
  17.         printf("\r\n");
  18.     }
  19.  
  20.     __DSB();
  21. }
  22.  
  23. void CAN_Handler(void)
  24. {
  25.     flexcan_frame_t flexcan_frame_tx;
  26.  
  27.     flexcan_frame_tx.length = 0x08;
  28.     flexcan_frame_tx.type   = (uint8_t)Enum_Flexcan_FrameTypeData;
  29.     flexcan_frame_tx.format = (uint8_t)Enum_Flexcan_FrameFormatStandard;
  30.     flexcan_frame_tx.id     = FLEXCAN_ID_STD(0x123);
  31.  
  32.     flexcan_frame_tx.dataWord0 = CAN_WORD0_DATA_BYTE_0(0x11) |
  33.                                  CAN_WORD0_DATA_BYTE_1(0x22) |
  34.                                  CAN_WORD0_DATA_BYTE_2(0x33) |
  35.                                  CAN_WORD0_DATA_BYTE_3(0x44);
  36.  
  37.     flexcan_frame_tx.dataWord1 = CAN_WORD1_DATA_BYTE_4(0x55) |
  38.                                  CAN_WORD1_DATA_BYTE_5(0x66) |
  39.                                  CAN_WORD1_DATA_BYTE_6(0x77) |
  40.                                  CAN_WORD1_DATA_BYTE_7(0x88);
  41.  
  42.     FLEXCAN_TransferSendBlocking(FLEX_CAN1, TX_MESSAGE_BUFFER_NUM, &flexcan_frame_tx);
  43. }
復(fù)制代碼

IrDA紅外通訊
在測(cè)試IrDA功能的時(shí)候需要搭配另外一塊IrDA功能板進(jìn)行測(cè)試,在上電的時(shí)候會(huì)自動(dòng)向外發(fā)送一串?dāng)?shù)據(jù),然后以中斷方式接收數(shù)據(jù)并通過(guò)調(diào)試終端軟件打印顯示出來(lái);實(shí)現(xiàn)代碼和測(cè)試效果如下:
  1. void UART2_IRQHandler(void)
  2. {
  3.     if(UART_GetITStatus(UART2, UART_IT_RXIEN) != RESET)
  4.     {
  5.         printf("%d ", UART_ReceiveData(UART2));
  6.         UART_ClearITPendingBit(UART2, UART_IT_RXIEN);
  7.     }
  8. }
  9.  
  10. void IrDA_SendData(uint8_t Data)
  11. {
  12.     UART_SendData(UART2, Data);
  13.     while(UART_GetFlagStatus(UART2, UART_IT_TXIEN) == RESET);
  14. }
  15.  
  16. void IrDA_Test(void)
  17. {
  18.     printf("\r\nIrDA TX : ");
  19.  
  20.     for(uint8_t i = 0; i < 10; i++)
  21.     {
  22.         IrDA_SendData(i);
  23.         printf("%d ", i);
  24.     }
  25.  
  26.     printf("\r\n");
  27. }
復(fù)制代碼

EEPROM數(shù)據(jù)存取
測(cè)試函數(shù)向EEPROM中先寫(xiě)入100字節(jié)數(shù)據(jù),再讀取到緩存數(shù)組,通過(guò)調(diào)試終端軟件打印顯示出來(lái)需要注意的是EEPROM是按PAGE進(jìn)行寫(xiě)入,每個(gè)PAGE的寫(xiě)入操作需要一段時(shí)間的間隔,這個(gè)代碼實(shí)現(xiàn)的時(shí)候需要特別注意;實(shí)現(xiàn)代碼和測(cè)試效果如下:
  1. void EEPROM_Test(void)
  2. {
  3.     uint8_t rBuffer[100], wBuffer[100];
  4.     uint8_t Address = 0,  Length = 100;
  5.  
  6.     printf("\r\n");
  7.  
  8.     for(uint8_t i = 0; i < Length; i++)
  9.     {
  10.         rBuffer[i] = 0;
  11.         wBuffer[i] = i + 100;
  12.     }
  13.  
  14.     printf("\r\nEEPROM Write......");
  15.  
  16.     EEPROM_WriteData(Address, wBuffer, Length);
  17.  
  18.     printf("\r\n");
  19.  
  20.     printf("\r\nEEPROM Read :");
  21.  
  22.     EEPROM_ReadData(Address, rBuffer, Length);
  23.  
  24.     for(uint8_t i = 0; i < Length; i++)
  25.     {
  26.         if((i % 16) == 0) printf("\r\n");
  27.  
  28.         printf("0x%02x ", rBuffer[i]);
  29.     }
  30.  
  31.     printf("\r\n");
  32. }
復(fù)制代碼

W25Q16數(shù)據(jù)存取
W25Q16用來(lái)保存WAV音頻文件和字庫(kù)文件,為了實(shí)現(xiàn)WAV播放音樂(lè)時(shí)流暢的效果,在讀取數(shù)據(jù)時(shí)應(yīng)盡可能的迅速,所以W25Q16的SPI接口使用DMA的通訊操作方式;在測(cè)試W25Q16時(shí)先對(duì)全片的所有SECTOR進(jìn)行擦除操作,然后驗(yàn)證寫(xiě)數(shù)據(jù)和讀數(shù)據(jù)的操作,實(shí)現(xiàn)代碼和測(cè)試效果如下:
  1. void W25Q16_Test(void)
  2. {
  3.     uint8_t Buffer[128];
  4.  
  5.     W25Q16_ReadDeviceID();
  6.  
  7.     W25Q16_ReadJEDEC_ID();
  8.  
  9.     for(uint16_t i = 0; i < 512; i++)
  10.     {
  11.         printf("\r\nW25Q16 Erase Sector[%03d]......", i);
  12.         W25Q16_SectorErase(i);
  13.     }
  14.  
  15.     printf("\r\n");
  16.  
  17.     printf("\r\nW25Q16 Erase Sector[0]......");
  18.     W25Q16_SectorErase(0);
  19.  
  20.     printf("\r\nW25Q16 Read :");
  21.     W25Q16_FastRead(0, Buffer, sizeof(Buffer));
  22.  
  23.     for(uint8_t i = 0; i < sizeof(Buffer); i++)
  24.     {
  25.         if((i % 16) == 0) printf("\r\n");
  26.  
  27.         printf("0x%02x ", Buffer[i]);
  28.     }
  29.  
  30.     printf("\r\n");
  31.  
  32.     printf("\r\nW25Q16 Write......");
  33.  
  34.     memset(Buffer, 0, sizeof(Buffer));
  35.  
  36.     for(uint8_t i = 0; i < sizeof(Buffer); i++)
  37.     {
  38.         Buffer[i] = i;
  39.     }
  40.  
  41.     W25Q16_PageProgram(0, Buffer, sizeof(Buffer));
  42.  
  43.     printf("\r\nW25Q16 Read :");
  44.  
  45.     W25Q16_FastRead(0, Buffer, sizeof(Buffer));
  46.  
  47.     for(uint8_t i = 0; i < sizeof(Buffer); i++)
  48.     {
  49.         if((i % 16) == 0) printf("\r\n");
  50.  
  51.         printf("0x%02x ", Buffer[i]);
  52.     }
  53.  
  54.     printf("\r\n");
  55. }
復(fù)制代碼

Xmodem下載文件/數(shù)據(jù)
Xmodem功能通過(guò)UART1接口,使用SecureCRT軟件將音頻文件和字庫(kù)文件下載到W25Q16存儲(chǔ)芯片中;實(shí)現(xiàn)代碼可以參考附件中的程序,也可以參考之前的Xmodem專題帖,測(cè)試效果如下:

LCD液晶顯示
LCD的控制接口與W25Q16共用了SPI1的SCK和MOSI這兩個(gè)引腳,但W25Q16需要發(fā)送數(shù)據(jù)和接收數(shù)據(jù)雙向功能,但LCD只需要發(fā)送數(shù)據(jù)即可;所以為了保證W25Q16數(shù)據(jù)讀寫(xiě)正常,在不操作W25Q16時(shí)需要將SPI1接收數(shù)據(jù)的功能關(guān)閉。。LCD實(shí)現(xiàn)了圖片顯示和中英文字符顯示,英文字符的字庫(kù)存放在程序空間,而中文字庫(kù)則存放在W25Q16存儲(chǔ)芯片,實(shí)現(xiàn)代碼和測(cè)試效果如下所示:
  1. void LCD_ShowLOG(uint8_t StartX, uint8_t StartY, const char *str)
  2. {
  3.     while(*str != '\0')
  4.     {
  5.         if(*str < 0x7F)
  6.         {
  7.             if(StartX > (128 - 8))
  8.             {
  9.                 StartX = 0; StartY += 16;
  10.             }
  11.  
  12.             if(StartY > (128 - 16))
  13.             {
  14.                 StartX = 0; StartY = 0;
  15.  
  16.                 LCD_ClearScreen(BACKCOLOR);
  17.             }
  18.  
  19.             LCD_ShowEN(StartX, StartY, *str);
  20.  
  21.             StartX += 0x08;
  22.             str    += 0x01;
  23.         }
  24.         else
  25.         {
  26.             if(StartX > (128 - 16))
  27.             {
  28.                 StartX = 0; StartY += 16;
  29.             }
  30.  
  31.             if(StartY > (128 - 16))
  32.             {
  33.                 StartX = 0; StartY = 0;
  34.  
  35.                 LCD_ClearScreen(BACKCOLOR);
  36.             }
  37.  
  38.             LCD_ShowCN(StartX, StartY,  str);
  39.  
  40.             StartX += 0x10;
  41.             str    += 0x02;
  42.         }
  43.     }
  44. }
  45.  
  46. void LCD_DrawImage(void)
  47. {
  48.     uint16_t Color = 0;
  49.     uint32_t Index = 0;
  50.  
  51.     for(uint32_t i = 0; i < 47; i++)
  52.     {
  53.         for(uint32_t j = 0; j < 128; j++)
  54.         {
  55.             Color   = gImage_**[Index++];
  56.             Color <<= 8;
  57.             Color  |= gImage_**[Index++];
  58.  
  59.             LCD_DrawPoint(j, i, Color);
  60.         }
  61.     }
  62. }
復(fù)制代碼

WAV播放音樂(lè)
通過(guò)讀取W25Q16存儲(chǔ)芯片中的WAV音樂(lè)文件,進(jìn)行解析,通過(guò)I2C接口將數(shù)據(jù)發(fā)送到HT5010功放芯片進(jìn)行音樂(lè)播放;I2S使用了雙緩存空間與DMA的數(shù)據(jù)傳輸方式,結(jié)合W25Q16存儲(chǔ)芯片DMA讀取數(shù)據(jù)的操作方式,加快數(shù)據(jù)讀取速度,使音樂(lè)播放效果更流暢;實(shí)現(xiàn)代碼和測(cè)試效果如下所示:
  1. void WAV_PlaySong(void)
  2. {
  3.     WAV_TypeDef WaveFile;
  4.  
  5.     if(WAV_PlayState == 0)
  6.     {
  7.         if(WAV_DecodeFile(&WaveFile, 0x00000000) == 0)
  8.         {
  9.             if((WaveFile.BitsPerSample == 16) && (WaveFile.nChannels == 2) &&
  10.                (WaveFile.SampleRate  > 44000) && (WaveFile.SampleRate < 48100))
  11.             {
  12.                 WAV_NextIndex = 0;
  13.                 WAV_PlayEnded = 0;
  14.                 WAV_TxLength  = 0;
  15.                 WAV_PlayState = 1;
  16.  
  17.                 printf("\r\n");
  18.                 printf("\r\nWAV Data Size : %d, Data Start : 0x%08x", WAV_DataSize, WAV_Offset);
  19.                 printf("\r\n");
  20.  
  21.                 WAV_PrepareData();
  22.                 WAV_PlayHandler();
  23.             }
  24.             else
  25.             {
  26.                 printf("\r\nWAV File Format Error!\r\n"); return;
  27.             }
  28.         }
  29.         else
  30.         {
  31.             printf("\r\nNo WAV File!\r\n"); return;
  32.         }
  33.     }
  34.     else
  35.     {
  36.         printf("\r\nThe Song Is Not Over Yet!\r\n");
  37.     }
  38. }
復(fù)制代碼

附件
軟件工程源代碼:
Template_DMA.zip (802.16 KB)

 

硬件設(shè)計(jì)原理圖:
4._SCH_PDF-P21-025-MCU-Hermes_V1.0_(_MM32F0140_EVK_)_Eagan_Yu_2022020.pdf (298.76 KB)

 

硬件BOM表、硬件PCB文檔:
9._BOM-P21-025-MCU-Hermes_V1.0_(_MM32F0140_EVK_)_Eagan_Yu_20220114.xls.zip (36.01 KB)
5._PCB-P21-025-MCU-Hermes_V1.0_(_MM32F0140_EVK_)_Eagan_Yu_20220120.pdf (1.58 MB)

 

器件手冊(cè):
CAT24C03.PDF (209.37 KB)
DS_MM32F0140_SC.pdf (2.75 MB)
HT5010.PDF (949.54 KB)
NCA1042.PDF (1.52 MB)
SGM6012.PDF (891.41 KB)
ST7735S.PDF (2.49 MB)
TFDU4300.PDF (190.66 KB)
W25Q16JV.PDF (1.63 MB)
01.TMF8821 Multizone Time-of-Flight Sensor.PDF (3.05 MB)
02.Host Driver Communication.PDF (2.02 MB)
03.ams Optical Sensors Design Recommendation for Systems EMI and ESD.PDF (1.04 MB)
04.TMF882X-SHIELD Quick Start Guide.PDF (997.41 KB)
05.TMF882X-EVM User Guide.PDF (1.52 MB)
06.TMF882X EVM Gorilla Glass Datasheet PI-Sheet-RevE.PDF (177.59 KB)
07.TMF882X Logfile Format Description.PDF (504.86 KB)
08.TMF882X Optical design guide.PDF (3.28 MB)
09.TMF8821 Software Development Kit Overview.PDF (531.76 KB)
10.TMF882x Shield Board Schematic &amp; Layout.PDF (5.01 MB)
TMF882x_Driver_MCU_Source_v3.51.zip (204.91 KB)
TMF882x_Driver_Sample_Code_v3.51.zip (8.14 KB)

 

資源文件:
GBK_FONT.zip (411.6 KB)
iPhone.zip (368.87 KB)


 

 
  • 本文系21ic原創(chuàng),未經(jīng)許可禁止轉(zhuǎn)載!

網(wǎng)友評(píng)論

  • 聯(lián)系人:巧克力娃娃
  • 郵箱:board@21ic.com
  • 我要投稿
  • 歡迎入駐,開(kāi)放投稿

熱門(mén)標(biāo)簽
項(xiàng)目外包 more+