首頁(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ā)板
- [導(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è)試效果如下:
- void RGBLED_Toggle(void)
- {
- static uint8_t Step = 0;
- switch(Step)
- {
- case 0:
- GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_RESET);
- GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET);
- GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_SET);
- break;
- case 1:
- GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_SET);
- GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET);
- GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_SET);
- break;
- case 2:
- GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_SET);
- GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET);
- GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_RESET);
- break;
- default:
- break;
- }
- Step = (Step + 1) % 3;
- }
獨(dú)立按鍵檢測(cè)
通過(guò)時(shí)間片輪轉(zhuǎn)調(diào)度的方式,軟件延時(shí)去抖處理,實(shí)現(xiàn)了4個(gè)按鍵的獨(dú)立檢測(cè),實(shí)現(xiàn)代碼和測(cè)試效果如下:
- void BUTTON_SubScan(uint8_t *State, uint8_t *Count, uint8_t Value, char *Name)
- {
- if(*State == 0)
- {
- if(Value == Bit_RESET) *Count += 1;
- else *Count = 0;
- if(*Count > 5)
- {
- *Count = 0; *State = 1;
- printf("\r\n%s Pressed", Name);
- }
- }
- else
- {
- if(Value != Bit_RESET) *Count += 1;
- else *Count = 0;
- if(*Count > 5)
- {
- *Count = 0; *State = 0;
- printf("\r\n%s Release", Name);
- }
- }
- }
- void BUTTON_Scan(void)
- {
- static uint8_t State[4] = {0, 0, 0, 0};
- static uint8_t Count[4] = {0, 0, 0, 0};
- BUTTON_SubScan(&State[0], &Count[0], GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0), "SW2");
- BUTTON_SubScan(&State[1], &Count[1], GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_2), "SW3");
- BUTTON_SubScan(&State[2], &Count[2], GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_3), "SW4");
- BUTTON_SubScan(&State[3], &Count[3], GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_2), "SW5");
- }
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è)試效果如下:
- void SWITCH_SubScan(uint8_t *State, uint8_t *Count, uint8_t Value, char *Name)
- {
- if(*State == 0)
- {
- if(Value != Bit_RESET) *Count += 1;
- else *Count = 0;
- if(*Count > 5)
- {
- *Count = 0; *State = 1;
- printf("\r\n%s -> OFF", Name);
- }
- }
- else
- {
- if(Value == Bit_RESET) *Count += 1;
- else *Count = 0;
- if(*Count > 5)
- {
- *Count = 0; *State = 0;
- printf("\r\n%s -> ON ", Name);
- }
- }
- }
- void SWITCH_Scan(void)
- {
- static uint8_t State[4] = {0, 0, 0, 0};
- static uint8_t Count[4] = {0, 0, 0, 0};
- SWITCH_SubScan(&State[0], &Count[0], GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15), "SW1-1");
- SWITCH_SubScan(&State[1], &Count[1], GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_15), "SW1-2");
- SWITCH_SubScan(&State[2], &Count[2], GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_14), "SW1-3");
- SWITCH_SubScan(&State[3], &Count[3], GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13), "SW1-4");
- }
ADC采樣
ADC包含了實(shí)現(xiàn)掉電壓檢測(cè)功能和可調(diào)電位器的電壓檢測(cè)這兩個(gè)功能,采用的單通道獨(dú)立查詢采樣的實(shí)現(xiàn)方式,實(shí)現(xiàn)代碼和測(cè)試效果如下:
- void ADC_Handler(void)
- {
- uint16_t Result = 0;
- float Voltage = 0.0;
- Result = ADC_Convert(ADC_Channel_10);
- Voltage = (float)Result / 4096 * 3.3;
- printf("\r\n");
- printf("\r\nPB3 <-> ADC1_CH10 : %0.3fV", Voltage);
- Result = ADC_Convert(ADC_Channel_12);
- Voltage = (float)Result / 4096 * 3.3;
- printf("\r\nPB7 <-> ADC1_CH12 : %0.3fV", Voltage);
- printf("\r\n");
- }
FlexCAN通訊
FlexCAN默認(rèn)配置為500kbps的通訊速率,每間隔3秒中向CAN總線中發(fā)送一個(gè)報(bào)文;配置了一個(gè)接收郵箱,采用中斷的方式,在接收到數(shù)據(jù)后通過(guò)調(diào)試終端軟件打印顯示出來(lái),實(shí)現(xiàn)代碼和測(cè)試效果如下:
- void FLEX_CAN_IRQHandler(void)
- {
- flexcan_frame_t flexcan_frame_rx;
- if(0U != FLEXCAN_GetMbStatusFlags(FLEX_CAN1, 1 << RX_MESSAGE_BUFFER_NUM))
- {
- FLEXCAN_ClearMbStatusFlags(FLEX_CAN1, 1 << RX_MESSAGE_BUFFER_NUM);
- FLEXCAN_ReadRxMb(FLEX_CAN1, RX_MESSAGE_BUFFER_NUM, &flexcan_frame_rx);
- printf("\r\nReceived message from MB%d", RX_MESSAGE_BUFFER_NUM);
- printf("\r\n");
- printf("\r\nrx form = 0x%x", (flexcan_frame_rx.id & CAN_ID_STD_MASK) >> CAN_ID_STD_SHIFT);
- printf("\r\nrx word0 = 0x%x", flexcan_frame_rx.dataWord0);
- printf("\r\nrx word1 = 0x%x", flexcan_frame_rx.dataWord1);
- printf("\r\n");
- }
- __DSB();
- }
- void CAN_Handler(void)
- {
- flexcan_frame_t flexcan_frame_tx;
- flexcan_frame_tx.length = 0x08;
- flexcan_frame_tx.type = (uint8_t)Enum_Flexcan_FrameTypeData;
- flexcan_frame_tx.format = (uint8_t)Enum_Flexcan_FrameFormatStandard;
- flexcan_frame_tx.id = FLEXCAN_ID_STD(0x123);
- flexcan_frame_tx.dataWord0 = CAN_WORD0_DATA_BYTE_0(0x11) |
- CAN_WORD0_DATA_BYTE_1(0x22) |
- CAN_WORD0_DATA_BYTE_2(0x33) |
- CAN_WORD0_DATA_BYTE_3(0x44);
- flexcan_frame_tx.dataWord1 = CAN_WORD1_DATA_BYTE_4(0x55) |
- CAN_WORD1_DATA_BYTE_5(0x66) |
- CAN_WORD1_DATA_BYTE_6(0x77) |
- CAN_WORD1_DATA_BYTE_7(0x88);
- FLEXCAN_TransferSendBlocking(FLEX_CAN1, TX_MESSAGE_BUFFER_NUM, &flexcan_frame_tx);
- }
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è)試效果如下:
- void UART2_IRQHandler(void)
- {
- if(UART_GetITStatus(UART2, UART_IT_RXIEN) != RESET)
- {
- printf("%d ", UART_ReceiveData(UART2));
- UART_ClearITPendingBit(UART2, UART_IT_RXIEN);
- }
- }
- void IrDA_SendData(uint8_t Data)
- {
- UART_SendData(UART2, Data);
- while(UART_GetFlagStatus(UART2, UART_IT_TXIEN) == RESET);
- }
- void IrDA_Test(void)
- {
- printf("\r\nIrDA TX : ");
- for(uint8_t i = 0; i < 10; i++)
- {
- IrDA_SendData(i);
- printf("%d ", i);
- }
- printf("\r\n");
- }
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è)試效果如下:
- void EEPROM_Test(void)
- {
- uint8_t rBuffer[100], wBuffer[100];
- uint8_t Address = 0, Length = 100;
- printf("\r\n");
- for(uint8_t i = 0; i < Length; i++)
- {
- rBuffer[i] = 0;
- wBuffer[i] = i + 100;
- }
- printf("\r\nEEPROM Write......");
- EEPROM_WriteData(Address, wBuffer, Length);
- printf("\r\n");
- printf("\r\nEEPROM Read :");
- EEPROM_ReadData(Address, rBuffer, Length);
- for(uint8_t i = 0; i < Length; i++)
- {
- if((i % 16) == 0) printf("\r\n");
- printf("0x%02x ", rBuffer[i]);
- }
- printf("\r\n");
- }
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è)試效果如下:
- void W25Q16_Test(void)
- {
- uint8_t Buffer[128];
- W25Q16_ReadDeviceID();
- W25Q16_ReadJEDEC_ID();
- for(uint16_t i = 0; i < 512; i++)
- {
- printf("\r\nW25Q16 Erase Sector[%03d]......", i);
- W25Q16_SectorErase(i);
- }
- printf("\r\n");
- printf("\r\nW25Q16 Erase Sector[0]......");
- W25Q16_SectorErase(0);
- printf("\r\nW25Q16 Read :");
- W25Q16_FastRead(0, Buffer, sizeof(Buffer));
- for(uint8_t i = 0; i < sizeof(Buffer); i++)
- {
- if((i % 16) == 0) printf("\r\n");
- printf("0x%02x ", Buffer[i]);
- }
- printf("\r\n");
- printf("\r\nW25Q16 Write......");
- memset(Buffer, 0, sizeof(Buffer));
- for(uint8_t i = 0; i < sizeof(Buffer); i++)
- {
- Buffer[i] = i;
- }
- W25Q16_PageProgram(0, Buffer, sizeof(Buffer));
- printf("\r\nW25Q16 Read :");
- W25Q16_FastRead(0, Buffer, sizeof(Buffer));
- for(uint8_t i = 0; i < sizeof(Buffer); i++)
- {
- if((i % 16) == 0) printf("\r\n");
- printf("0x%02x ", Buffer[i]);
- }
- printf("\r\n");
- }
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è)試效果如下所示:
- void LCD_ShowLOG(uint8_t StartX, uint8_t StartY, const char *str)
- {
- while(*str != '\0')
- {
- if(*str < 0x7F)
- {
- if(StartX > (128 - 8))
- {
- StartX = 0; StartY += 16;
- }
- if(StartY > (128 - 16))
- {
- StartX = 0; StartY = 0;
- LCD_ClearScreen(BACKCOLOR);
- }
- LCD_ShowEN(StartX, StartY, *str);
- StartX += 0x08;
- str += 0x01;
- }
- else
- {
- if(StartX > (128 - 16))
- {
- StartX = 0; StartY += 16;
- }
- if(StartY > (128 - 16))
- {
- StartX = 0; StartY = 0;
- LCD_ClearScreen(BACKCOLOR);
- }
- LCD_ShowCN(StartX, StartY, str);
- StartX += 0x10;
- str += 0x02;
- }
- }
- }
- void LCD_DrawImage(void)
- {
- uint16_t Color = 0;
- uint32_t Index = 0;
- for(uint32_t i = 0; i < 47; i++)
- {
- for(uint32_t j = 0; j < 128; j++)
- {
- Color = gImage_**[Index++];
- Color <<= 8;
- Color |= gImage_**[Index++];
- LCD_DrawPoint(j, i, Color);
- }
- }
- }
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è)試效果如下所示:
- void WAV_PlaySong(void)
- {
- WAV_TypeDef WaveFile;
- if(WAV_PlayState == 0)
- {
- if(WAV_DecodeFile(&WaveFile, 0x00000000) == 0)
- {
- if((WaveFile.BitsPerSample == 16) && (WaveFile.nChannels == 2) &&
- (WaveFile.SampleRate > 44000) && (WaveFile.SampleRate < 48100))
- {
- WAV_NextIndex = 0;
- WAV_PlayEnded = 0;
- WAV_TxLength = 0;
- WAV_PlayState = 1;
- printf("\r\n");
- printf("\r\nWAV Data Size : %d, Data Start : 0x%08x", WAV_DataSize, WAV_Offset);
- printf("\r\n");
- WAV_PrepareData();
- WAV_PlayHandler();
- }
- else
- {
- printf("\r\nWAV File Format Error!\r\n"); return;
- }
- }
- else
- {
- printf("\r\nNo WAV File!\r\n"); return;
- }
- }
- else
- {
- printf("\r\nThe Song Is Not Over Yet!\r\n");
- }
- }
附件
軟件工程源代碼:
硬件設(shè)計(jì)原理圖:
硬件BOM表、硬件PCB文檔:
器件手冊(cè):
資源文件:
- 本文系21ic原創(chuàng),未經(jīng)許可禁止轉(zhuǎn)載!
網(wǎng)友評(píng)論
- 聯(lián)系人:巧克力娃娃
- 郵箱:board@21ic.com
- 我要投稿
-
歡迎入駐,開(kāi)放投稿
行業(yè)新聞
熱門(mén)標(biāo)簽
論壇活動(dòng)
more+
公開(kāi)課
more+
項(xiàng)目外包
more+
- NRF52810藍(lán)牙數(shù)字耳機(jī)找人定制
預(yù)算:¥30005天前
- 125KW模塊式PCS軟硬件外包開(kāi)發(fā)
預(yù)算:¥1100000015小時(shí)前
- 12V汽車啟動(dòng)電源項(xiàng)目BMS設(shè)計(jì)
預(yù)算:¥50000023小時(shí)前
- 數(shù)據(jù)可視化軟件 開(kāi)發(fā)
預(yù)算:¥5000023小時(shí)前
- PLC項(xiàng)目調(diào)試修改
預(yù)算:¥100001天前
- 起動(dòng)電機(jī)控制器開(kāi)發(fā)
預(yù)算:¥1100001天前