#申请原创# @21小跑堂
简介 MM32L0130系列MCU是灵动微电子新推出的低功耗产品,内核使用32位的高性能Arm® Cortex-M0+ 微控制器,最高工作频率可达到48MHz,内置高速存储器,丰富的增强型 I/O 端口和多种外设。可适用于空调遥控器、温控器、耳/额温枪、便携医疗设备、气/水/电等仪表、小家电等应用领域。
MM32L0130系列MCU主要特性 u 内核与系统 Ø 32-bit Arm® Cortex®-M0+ Ø 工作频率可达48MHz u 存储器 Ø 多达 64KB 的 Flash 存储器 Ø 多达 8KB SRAM Ø Boot loader 支持片内 Flash 在线系统编程(ISP) u 时钟、复位和电源管理 Ø 1.8V ∼ 5.5V 供电 Ø 上电/断电复位(POR/PDR) 、可编程电压监测器(PVD) Ø 外部 4 ∼ 24MHz 高速晶体振荡器 Ø 外部 32.768KHz 低速振荡器(带 LSE Bypass 功能) Ø 内置经出厂调校的8MHz 高速 RC 振荡器,全温度范围内偏差不超过 ±2.5% Ø PLL 支持 CPU 最高运行在 48MHz,支持多种分频模式 Ø 内置 16.384KHz 低速振荡器,全温度范围内频率偏差不超过 ±3.5% u 低功耗 Ø 多种低功耗模式,包括:低功耗运行(Low Power Run)、睡眠(Sleep)、低功耗睡眠(Low Power Sleep)、停机(Stop)、深度停机(Deep Stop)、 待机(Standby)和关机(Shutdown)模式 u 1 个 5 通道 DMA 控制器,支持外设类型包括定时器、ADC、UART、LPUART、I2C、SPI 和SLCD u 9 个定时器 Ø 2 个 16 位通用定时器(TIM3 /TIM4),有多达 4 个输入捕获/输出比较通道,可用于IR 控制解码 Ø 2 个 16 位基本定时器(TIM16/ TIM17),有 1 个输入捕获/输出比较通道,1 组互补输出, 支持死区生成,紧急停止, 调制器门电路用于 IR 控制 Ø 1 个低功耗定时器(LPTIM),可在除待机和关机模式外的所有模式唤醒 CPU Ø 2 个看门狗定时器(独立型的 IWDG 和窗口型的 WWDG) Ø 1 个 RTC 计数器,支持日历功能 Ø 1 个 Systick 定时器: 24 位自减型计数器 u 多达 57 个快速 I/O 端口: Ø 所有 I/O 口可以映像到 16 个外部中断 Ø 所有端口均可输入输出电压不高于VDD 的信号 u 多达 6 个通信接口 Ø 2 个 UART 接口 Ø 1 个低功耗 UART 接口(LPUART) Ø 1 个 I2C 接口 Ø 2 个 SPI 接口(2 个I2S 接口) u 1 个红外信号调制模块(Infra-Red Modulator, IRM),支持 ASK/PSK/FSK 调制 u 1 个段码式液晶驱动模块(SLCD),可驱动 40x4 或 36x8 个段码 u 1 个 12 位模数转换器(ADC),1us 转换时间,多达 15 个外部输入通道,1个内部输入通道 Ø 转换范围:0 ∼ VDDA Ø 支持采样时间和分辨率配置 Ø 片上温度传感器 Ø 片上电压传感器 u 1 个比较器 u CRC 计算单元,8/16/32 位多项式可配置 u 96 位芯片唯一 ID(UID) u 调试模式 Ø 串行调试接口(SWD) 接口 u 采用 LQFP64 和 LQFP48 封装
准备开发环境 1、EVB-L0130开发板 2、J-LINK调试下载器 3、USB转TLL工具 4、音箱、USB数据线 EVB-L0130属于MM32EVBoard系列开发板,板载芯片为MM32L0136C7P,带有丰富的外设资源:支持高达 4KV EFT 抗干扰能力、支持 SWD 下载调试接口、4个用户按键、1个复位按键、4个用户LED、2路UART 连接器、1个给开发板供电USB 连接器、1个8Mbit 的 SPI Flash 存储器、1个2048bit 的 I2C 存储器、4个功能选择开关(I2S或是LCD)、1个3.5mm 耳机插座,用于 I2SL/R 音频输出、1个无源扬声器、3路模拟输入电位器、1个板载段码 LCD显示屏……
准备相关资料
实现功能 1. 基于EVB-L0130创建基础工程,移植MultiTime开源软件库,结合SysTick定时器实现系统的任务管理和调度 2. 移植Letter-shell_2.x开源软件库,结合板载的UART1接口,实现串口打印、在线联机调试的功能 3. 实现板载4颗LED灯的闪烁控制 4. 移植MultiButton开源软件库,结合板载的4个功能按键,实现按键扫描、检测和处理的功能 5. 通过DMA中断方式实现对板载3路模拟量输入的ADC采样,可通过实时看到当前的采样结果 6. 通过MCU的硬件I2C接口,对板载有EEPROM存储芯片进行读写操作 7. 移植SFUD开源软件库,再通过MCU的硬件SPI接口,对板载的SPIFLASH存储芯片进行读、写、擦除等操作 8. 通过TIM定时器的PWM输出功能,实现对板载蜂鸣器的控制,让其发出指定的提示音 9. 结合段位LCD显示屏的真值表、MCU与LCD的硬件连接,实现对板载LCD的显示驱动,通过查表方式,实现灵活显示,便程序更具有可读性、更便于移植和功能实现 10. 通过MCU内部自带的RTC模块,再结合段位LCD显示屏,实现实时时钟显示的功能,通过软件代码实现自动初始化日期、时间的功能 11. 通过板载的IRDA发送头和接收头,结合MCU内部自带的IRM模块实现红外数据的发送、接收功能 12. 通过实现XMODEM传输协议与SPI FLASH的读写操作,实现上位机软件将数据/文件写入到板载SPI FLASH存储芯片的功能,对于XMODEM的通讯操作使用了消息队列的处理方式 13. 通过I2S接口,实现播放SPI FLASH存储芯片中存放的WAV音频文件,通过音箱进行播放;在播放过程中我们使用DMA加双缓存,通过乒乓操作的方式进行,让音频播放更加流畅,不至于出现卡顿的效果
实验过程中需要注意点: 1、上述所有的功能均已实现,有基于MindSDK和LibSample标准库两个版本,根据个人习惯选择相应版本,对于作者而言,这两个其实都差不多,只是底层不太一样,上层的功能和应用没有太大影响 2、所有的功能可以单独测试,也可以组合测试,可以通过修改config.h头文件中的宏定义来开关相对应的功能 3、EVB-L0130开发板上有4个切换开关,是用来切换MCU的GPIO是用来控制LCD显示的,还是用来操作I2S播放音频的,所以在做LCD和I2S实验时,需要将这4个切换开关拨正确,这两个功能的实验也不能同时完成 4、通过EVB-L0130开发板的原理图,我们看到MCU与LCD的连接部分,LCD并不是所有的引脚都连接到MCU上的,这就导致LCD上的段位不可能显示完全 5、我手上的EVB-L0130是初代的版本,暂时还做不了低功耗的测试,这个官方应该会地后面的硬件版本上更新过来吧……
ADC & DMA功能实现: - #if ENABLE_ADC
- /* Private typedef -----------------------------------------------------------*/
- /* Private define ------------------------------------------------------------*/
- /* Private macro -------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- MultiTimer ADC_MultiTimer;
- /* Private variables ---------------------------------------------------------*/
- float RV1_Voltage = 0.0;
- float RV2_Voltage = 0.0;
- float RV3_Voltage = 0.0;
- /* Private variables ---------------------------------------------------------*/
- uint16_t ADC_Flag = 0;
- uint16_t ADC_Buffer[30];
- /* Private function prototypes -----------------------------------------------*/
- /* Private functions ---------------------------------------------------------*/
- /* Exported variables --------------------------------------------------------*/
- /* Exported function prototypes ----------------------------------------------*/
- /*******************************************************************************
- * [url=home.php?mod=space&uid=247401]@brief[/url]
- * @param
- * @retval
- * [url=home.php?mod=space&uid=93590]@Attention[/url]
- *******************************************************************************/
- void ADC_MultiTimerCallback(MultiTimer *timer, void *userData)
- {
- uint32_t ADC0_Value = 0;
- uint32_t ADC1_Value = 0;
- uint32_t ADC2_Value = 0;
- if(ADC_Flag == 1)
- {
- ADC_Flag = 0;
- for(uint8_t i = 0; i < 30;)
- {
- ADC0_Value += ADC_Buffer[i++];
- ADC1_Value += ADC_Buffer[i++];
- ADC2_Value += ADC_Buffer[i++];
- }
- RV1_Voltage = ((float)(ADC0_Value) / 4096.0) * 3.3 / 10.0;
- RV2_Voltage = ((float)(ADC1_Value) / 4096.0) * 3.3 / 10.0;
- RV3_Voltage = ((float)(ADC2_Value) / 4096.0) * 3.3 / 10.0;
- ADC_SoftwareStartConvCmd(ADC1, ENABLE);
- }
- MultiTimerStart(&ADC_MultiTimer, 250, ADC_MultiTimerCallback, "ADC");
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void mADC_Init(void)
- {
- ADC_InitTypeDef ADC_InitStructure;
- DMA_InitTypeDef DMA_InitStruct;
- GPIO_InitTypeDef GPIO_InitStructure;
- NVIC_InitTypeDef NVIC_InitStruct;
- RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);
- GPIO_StructInit(&GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel1_IRQn;
- NVIC_InitStruct.NVIC_IRQChannelPriority = 2;
- NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStruct);
- RCC_AHBPeriphClockCmd(RCC_AHBENR_DMA1, ENABLE);
- DMA_DeInit(DMA1_Channel1);
- DMA_StructInit(&DMA_InitStruct);
- DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR);
- DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&ADC_Buffer;
- DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
- DMA_InitStruct.DMA_BufferSize = 30;
- DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
- DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
- DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
- DMA_InitStruct.DMA_Priority = DMA_Priority_High;
- DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
- DMA_InitStruct.DMA_Auto_reload = DMA_Auto_Reload_Disable;
- DMA_Init(DMA1_Channel1, &DMA_InitStruct);
- if(DMA_InitStruct.DMA_PeripheralBaseAddr == ((uint32_t)(&ADC1->DR)))
- {
- DMA_SetChannelMuxSource(DMA1_Channel1, DMA1_MUX_ADC1);
- if(DMA_GetChannelMuxSource(DMA1_Channel1) != DMA1_MUX_ADC1)
- {
- while(1);
- }
- }
- DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
- DMA_Cmd(DMA1_Channel1, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2ENR_ADC1, ENABLE);
- ADC_StructInit(&ADC_InitStructure);
- ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
- ADC_InitStructure.ADC_PRESCARE = ADC_PCLK2_PRESCARE_16;
- ADC_InitStructure.ADC_Mode = ADC_Mode_Continue;
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
- ADC_InitStructure.ADC_ExternalTrigConv = ADC1_ExternalTrigConv_T3_CC3;
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
- ADC_Init(ADC1, &ADC_InitStructure);
- ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 0, ADC_Samctl_240_5);
- ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_Samctl_240_5);
- ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2, ADC_Samctl_240_5);
- ADC_DMACmd(ADC1, ENABLE);
- ADC_Cmd(ADC1, ENABLE);
- ADC_SoftwareStartConvCmd(ADC1, ENABLE);
- MultiTimerStart(&ADC_MultiTimer, 250, ADC_MultiTimerCallback, "ADC");
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void DMA1_Channel1_IRQHandler(void)
- {
- ADC_SoftwareStartConvCmd(ADC1, DISABLE);
- DMA_ClearITPendingBit(DMA1_IT_TC1);
- ADC_Flag = 1;
- }
- #endif
BUZZER & TIM & PWM功能实现: - #if ENABLE_BUZZER
- /* Private typedef -----------------------------------------------------------*/
- /* Private define ------------------------------------------------------------*/
- /* Private macro -------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- MultiTimer BUZZER_MultiTimer;
- /* Private variables ---------------------------------------------------------*/
- BUZZER_TypeDef BUZZER_TAB[] =
- {
- {50, 100, 1},
- {50, 100, 1},
- {50, 100, 0},
- };
- /* Private variables ---------------------------------------------------------*/
- volatile uint8_t BUZZER_Flag = 0;
- /* Private function prototypes -----------------------------------------------*/
- /* Private functions ---------------------------------------------------------*/
- /* Exported variables --------------------------------------------------------*/
- /* Exported function prototypes ----------------------------------------------*/
- #if 1
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void BUZZER_MultiTimerCallback(MultiTimer *timer, void *userData)
- {
- static uint8_t State = 0, Index = 0;
- if(State == 0)
- {
- State = 1; BUZZER_Flag = 1;
- MultiTimerStart(&BUZZER_MultiTimer, BUZZER_TAB[Index].PlayMS, BUZZER_MultiTimerCallback, "BUZZER");
- }
- else
- {
- State = 0; BUZZER_Flag = 0;
- if(BUZZER_TAB[Index].KeepOn)
- {
- MultiTimerStart(&BUZZER_MultiTimer, BUZZER_TAB[Index++].WaitMS, BUZZER_MultiTimerCallback, "BUZZER");
- }
- else
- {
- Index = 0;
- }
- }
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void BUZZER_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- RCC_ClocksTypeDef RCC_Clocks;
- RCC_GetClocksFreq(&RCC_Clocks);
- RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);
- GPIO_StructInit(&GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- NVIC_InitStructure.NVIC_IRQChannel = TIM16_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- RCC_APB2PeriphClockCmd(RCC_APB2ENR_TIM16, ENABLE);
- TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
- TIM_TimeBaseStructure.TIM_Prescaler = (RCC_Clocks.SYSCLK_Frequency / 1000000 - 1);
- TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
- TIM_TimeBaseStructure.TIM_Period = (500 - 1);
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
- TIM_TimeBaseInit(TIM16, &TIM_TimeBaseStructure);
- TIM_ITConfig(TIM16, TIM_IT_Update, ENABLE);
- TIM_Cmd(TIM16, ENABLE);
- MultiTimerStart(&BUZZER_MultiTimer, 100, BUZZER_MultiTimerCallback, "BUZZER");
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void TIM16_IRQHandler(void)
- {
- static BitAction Value = Bit_RESET;
- if(TIM_GetITStatus(TIM16, TIM_IT_Update) != RESET)
- {
- if(BUZZER_Flag == 1)
- {
- if(Value == Bit_RESET) Value = Bit_SET;
- else Value = Bit_RESET;
- GPIO_WriteBit(GPIOA, GPIO_Pin_6, Value);
- }
- TIM_ClearITPendingBit(TIM16, TIM_IT_Update);
- }
- }
- #else
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void BUZZER_MultiTimerCallback(MultiTimer *timer, void *userData)
- {
- static uint8_t State = 0, Index = 0;
- if(State == 0)
- {
- State = 1; TIM_SetCompare1(TIM3, 500);
- MultiTimerStart(&BUZZER_MultiTimer, BUZZER_TAB[Index].PlayMS, BUZZER_MultiTimerCallback, "BUZZER");
- }
- else
- {
- State = 0; TIM_SetCompare1(TIM3, 0);
- if(BUZZER_TAB[Index].KeepOn)
- {
- MultiTimerStart(&BUZZER_MultiTimer, BUZZER_TAB[Index++].WaitMS, BUZZER_MultiTimerCallback, "BUZZER");
- }
- else
- {
- Index = 0;
- }
- }
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void BUZZER_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
- RCC_ClocksTypeDef RCC_Clocks;
- RCC_GetClocksFreq(&RCC_Clocks);
- RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);
- GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_1);
- GPIO_StructInit(&GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- RCC_APB1PeriphClockCmd(RCC_APB1ENR_TIM3, ENABLE);
- TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
- TIM_TimeBaseStructure.TIM_Prescaler = (RCC_Clocks.PCLK1_Frequency / 1000000 - 1);
- TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
- TIM_TimeBaseStructure.TIM_Period = (1000 - 1);
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
- TIM_OCStructInit(&TIM_OCInitStructure);
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
- TIM_OCInitStructure.TIM_Pulse = 0;
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
- TIM_OC1Init(TIM3, &TIM_OCInitStructure);
- TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
- TIM_ARRPreloadConfig(TIM3, ENABLE);
- TIM_Cmd(TIM3, ENABLE);
- TIM_CtrlPWMOutputs(TIM3, ENABLE);
- MultiTimerStart(&BUZZER_MultiTimer, 100, BUZZER_MultiTimerCallback, "BUZZER");
- }
- #endif
- #endif
EEPROM & I2C功能实现: - #if ENABLE_EEPROM
- /* Private typedef -----------------------------------------------------------*/
- /* Private define ------------------------------------------------------------*/
- /* Private macro -------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- /* Private function prototypes -----------------------------------------------*/
- /* Private functions ---------------------------------------------------------*/
- /* Exported variables --------------------------------------------------------*/
- /* Exported function prototypes ----------------------------------------------*/
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void I2C_GetBuffer(uint8_t Address, uint8_t *Buffer, uint8_t Length)
- {
- uint8_t Flag = 0, Count = 0;
- I2C_SendData(I2C1, Address);
- while(!I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE));
- for(uint8_t i = 0; i < Length; i++)
- {
- while(1)
- {
- if((I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFNF)) && (Flag == 0))
- {
- I2C_ReadCmd(I2C1); Count++;
- if(Count == Length) Flag = 1;
- }
- if(I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_RFNE))
- {
- Buffer[i] = I2C_ReceiveData(I2C1); break;
- }
- }
- }
- I2C_GenerateSTOP(I2C1, ENABLE);
- while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_STOP_DET));
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void I2C_PutBuffer(uint8_t Address, uint8_t *Buffer, uint8_t Length)
- {
- I2C_SendData(I2C1, Address);
- while(!I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE));
- for(uint8_t i = 0; i < Length; i++)
- {
- I2C_SendData(I2C1, *Buffer++);
- while(!I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE));
- }
- I2C_GenerateSTOP(I2C1, ENABLE);
- while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_STOP_DET));
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void EEPROM_ReadData(uint8_t Address, uint8_t *Buffer, uint8_t Length)
- {
- I2C_GetBuffer(Address, Buffer, Length);
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void EEPROM_WriteData(uint8_t Address, uint8_t *Buffer, uint8_t Length)
- {
- uint8_t Start, StartCount, PageNumber, FinalCount;
- if((Address % EEPROM_PAGE_SIZE) == 0)
- {
- StartCount = 0;
- PageNumber = Length / EEPROM_PAGE_SIZE;
- FinalCount = Length % EEPROM_PAGE_SIZE;
- }
- else
- {
- Start = Address % EEPROM_PAGE_SIZE;
- if(((Start + Length) / EEPROM_PAGE_SIZE) == 0)
- {
- StartCount = Length;
- PageNumber = 0;
- FinalCount = 0;
- }
- else
- {
- StartCount = EEPROM_PAGE_SIZE - Start;
- PageNumber = (Length - StartCount) / EEPROM_PAGE_SIZE;
- FinalCount = (Length - StartCount) % EEPROM_PAGE_SIZE;
- }
- }
- if(StartCount)
- {
- I2C_PutBuffer(Address, Buffer, StartCount);
- Address += StartCount;
- Buffer += StartCount;
- printf("\r\nWait A Moument..."); SysTick_DelayMS(10);
- }
- while(PageNumber--)
- {
- I2C_PutBuffer(Address, Buffer, EEPROM_PAGE_SIZE);
- Address += EEPROM_PAGE_SIZE;
- Buffer += EEPROM_PAGE_SIZE;
- printf("\r\nWait A Moument..."); SysTick_DelayMS(10);
- }
- if(FinalCount)
- {
- I2C_PutBuffer(Address, Buffer, FinalCount);
- }
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void EEPROM_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- I2C_InitTypeDef I2C_InitStructure;
- RCC_APB1PeriphClockCmd(RCC_APB1ENR_I2C1, ENABLE);
- I2C_StructInit(&I2C_InitStructure);
- I2C_InitStructure.I2C_Mode = I2C_Mode_MASTER;
- I2C_InitStructure.I2C_OwnAddress = 0;
- I2C_InitStructure.I2C_Speed = I2C_Speed_STANDARD;
- I2C_InitStructure.I2C_ClockSpeed = 100000;
- I2C_Init(I2C1, &I2C_InitStructure);
- I2C_Send7bitAddress(I2C1, EEPROM_I2C_ADDRESS, I2C_Direction_Transmitter);
- I2C_Cmd(I2C1, ENABLE);
- RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOB, ENABLE);
- GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_3);
- GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_3);
- GPIO_StructInit(&GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void EEPROM_Demo(void)
- {
- uint8_t rBuffer[20], wBuffer[20];
- uint8_t Address = 0;
- uint8_t Length = 20;
- for(uint8_t i = 0; i < Length; i++)
- {
- rBuffer[i] = 0;
- wBuffer[i] = i;
- }
- printf("\r\n\r\nEEPROM Write Data : ");
- EEPROM_WriteData(Address, wBuffer, Length);
- printf("OK"); SysTick_DelayMS(10);
- printf("\r\n\r\nEEPROM Read Data : \r\n");
- EEPROM_ReadData(Address, rBuffer, Length);
- for(uint8_t i = 0; i < Length; i++)
- {
- printf("0x%02x ", rBuffer[i]);
- if(((i + 1) % 10) == 0) printf("\r\n");
- }
- printf("\r\n\r\n");
- }
- #endif
SPI FLASH & SFUD功能实现: - /* Includes ------------------------------------------------------------------*/
- #include <sfud.h>
- /* Private typedef -----------------------------------------------------------*/
- /* Private define ------------------------------------------------------------*/
- #define SFUD_DEMO_BUFFER_SIZE (512)
- /* Private macro -------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- uint8_t sfud_demo_buf[SFUD_DEMO_BUFFER_SIZE];
- /* Private function prototypes -----------------------------------------------*/
- /* Private functions ---------------------------------------------------------*/
- /* Exported variables --------------------------------------------------------*/
- /* Exported function prototypes ----------------------------------------------*/
- /*******************************************************************************
- * @brief SFUD demo for the first flash device test
- * @param addr flash start address
- * @param size test flash size
- * @param size test flash data buffer
- * @retval
- * @attention
- *******************************************************************************/
- void sfud_demo(uint32_t addr, size_t size, uint8_t *data)
- {
- sfud_err result = SFUD_SUCCESS;
- const sfud_flash *flash = sfud_get_device_table() + 0;
- size_t i;
- /* prepare write data */
- for(i = 0; i < size; i++)
- {
- data[i] = i;
- }
- /* erase test */
- result = sfud_erase(flash, addr, size);
- if(result == SFUD_SUCCESS)
- {
- printf("\r\nErase the %s flash data finish. Start from 0x%08X, size is %d.\r\n", flash->name, addr, size);
- }
- else
- {
- printf("\r\nErase the %s flash data failed.\r\n", flash->name);
- return;
- }
- /* write test */
- result = sfud_write(flash, addr, size, data);
- if(result == SFUD_SUCCESS)
- {
- printf("\r\nWrite the %s flash data finish. Start from 0x%08X, size is %d.\r\n", flash->name, addr, size);
- }
- else
- {
- printf("\r\nWrite the %s flash data failed.\r\n", flash->name);
- return;
- }
- /* read test */
- result = sfud_read(flash, addr, size, data);
- if(result == SFUD_SUCCESS)
- {
- printf("\r\nRead the %s flash data success. Start from 0x%08X, size is %d. The data is:\r\n", flash->name, addr, size);
- printf("Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\r\n");
- for(i = 0; i < size; i++)
- {
- if((i % 16) == 0)
- {
- printf("[%08X] ", addr + i);
- }
- printf("%02X ", data[i]);
- if(((i + 1) % 16 == 0) || (i == size - 1))
- {
- printf("\r\n");
- }
- }
- printf("\r\n");
- }
- else
- {
- printf("\r\nRead the %s flash data failed.\r\n", flash->name);
- }
- /* data check */
- for(i = 0; i < size; i++)
- {
- if(data[i] != i % 256)
- {
- printf("\r\nRead and check write data has an error. Write the %s flash data failed.\r\n", flash->name);
- break;
- }
- }
- if(i == size)
- {
- printf("\r\nThe %s flash test is success.\r\n", flash->name);
- }
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void SPI_FLASH_Init(void)
- {
- printf("\r\n");
- if(sfud_init() == SFUD_SUCCESS)
- {
- sfud_demo(0, sizeof(sfud_demo_buf), sfud_demo_buf);
- }
- }
RTC & LCD功能实现: - #if ENABLE_RTC
- /* Private typedef -----------------------------------------------------------*/
- /* Private define ------------------------------------------------------------*/
- /* Private macro -------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- MultiTimer RTC_MultiTimer;
- /* Private function prototypes -----------------------------------------------*/
- /* Private functions ---------------------------------------------------------*/
- /* Exported variables --------------------------------------------------------*/
- /* Exported function prototypes ----------------------------------------------*/
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- uint8_t RTC_GetWeek(uint16_t Year, uint8_t Month, uint8_t Day)
- {
- int w, c, y;
- /* Month 1 Or 2 of This Year Must Be As Last Month 13 Or 14 */
- if((Month == 1) || (Month == 2))
- {
- Month += 12;
- Year -= 1;
- }
- w = 0; /* Weekday */
- c = Year / 100; /* Century */
- y = Year % 100; /* Year */
- w = y + (y / 4) + (c / 4) - (2 * c) + (26 * (Month + 1) / 10) + Day - 1;
- while(w < 0) w += 7;
- w %= 7;
- return w;
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void RTC_LoadDefault(RTCCAL_DateTypeDef *RTCCAL_Date, RTCCAL_TimeTypeDef *RTCCAL_Time)
- {
- char date[20], time[20];
- char text[6][5];
- uint8_t index = 0, month = 0;
- memset(date, 0, sizeof(date));
- memset(time, 0, sizeof(time));
- memset(text, 0, sizeof(text));
- memcpy(date, __DATE__, sizeof(__DATE__));
- memcpy(time, __TIME__, sizeof(__TIME__));
- char *str;
- str = strtok(date, " ");
- while(str != NULL)
- {
- memcpy(text[index], str, strlen(str));
- index++;
- str = strtok(NULL, " ");
- }
- str = strtok(time, ":");
- while(str != NULL)
- {
- memcpy(text[index], str, strlen(str));
- index++;
- str = strtok(NULL, ":");
- }
- #if 0
- for(uint8_t i = 0; i < index; i++)
- {
- printf("\r\n->%s", text[i]);
- }
- #endif
- char *strMonth[12] =
- {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
- };
- for(uint8_t i = 0; i < 12; i++)
- {
- if(strcmp(text[0], strMonth[i]) == 0)
- {
- month = i + 1;
- }
- }
- RTCCAL_Date->RTCCAL_Date = atoi(text[1]);
- RTCCAL_Date->RTCCAL_Month = month;
- RTCCAL_Date->RTCCAL_Year = atoi(text[2]) - 2000;
- RTCCAL_Date->RTCCAL_WeekDay = RTC_GetWeek(RTCCAL_Date->RTCCAL_Year + 2000,
- RTCCAL_Date->RTCCAL_Month,
- RTCCAL_Date->RTCCAL_Date);
- RTCCAL_Time->RTCCAL_Hours = atoi(text[3]);
- RTCCAL_Time->RTCCAL_Minutes = atoi(text[4]);
- RTCCAL_Time->RTCCAL_Seconds = atoi(text[5]);
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void RTC_MultiTimerCallback(MultiTimer *timer, void *userData)
- {
- RTCCAL_TimeTypeDef RTCCAL_TimeStructure;
- RTCCAL_DateTypeDef RTCCAL_DateStructure;
- RTCCAL_GetTime(RTCCAL_Format_BIN, &RTCCAL_TimeStructure);
- RTCCAL_GetDate(RTCCAL_Format_BIN, &RTCCAL_DateStructure);
- #if ENABLE_LCD
- LCD_DisplayNumber2(0, '0' + (RTCCAL_TimeStructure.RTCCAL_Hours / 10), 0);
- LCD_DisplayNumber2(1, '0' + (RTCCAL_TimeStructure.RTCCAL_Hours % 10), 0);
- LCD_DisplayNumber2(2, '0' + (RTCCAL_TimeStructure.RTCCAL_Minutes / 10), 0);
- LCD_DisplayNumber2(3, '0' + (RTCCAL_TimeStructure.RTCCAL_Minutes % 10), 0);
- LCD_DisplayNumber2(4, '0' + (RTCCAL_TimeStructure.RTCCAL_Seconds / 10), 0);
- LCD_DisplayNumber2(5, '0' + (RTCCAL_TimeStructure.RTCCAL_Seconds % 10), 0);
- #else
- printf("\r\n%04d-%02d-%02d", RTCCAL_DateStructure.RTCCAL_Year + 2000, RTCCAL_DateStructure.RTCCAL_Month, RTCCAL_DateStructure.RTCCAL_Date);
- switch(RTCCAL_DateStructure.RTCCAL_WeekDay)
- {
- case 0 : printf(" SUN "); break;
- case 1 : printf(" MON "); break;
- case 2 : printf(" TUE "); break;
- case 3 : printf(" WED "); break;
- case 4 : printf(" THU "); break;
- case 5 : printf(" FRI "); break;
- case 6 : printf(" SAT "); break;
- default: break;
- }
- printf("%02d:%02d:%02d\r\n", RTCCAL_TimeStructure.RTCCAL_Hours, RTCCAL_TimeStructure.RTCCAL_Minutes, RTCCAL_TimeStructure.RTCCAL_Seconds);
- #endif
- MultiTimerStart(&RTC_MultiTimer, 500, RTC_MultiTimerCallback, "RTC");
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void RTC_Init(void)
- {
- RTCCAL_InitTypeDef RTCCAL_InitStructure;
- RTCCAL_TimeTypeDef RTCCAL_TimeStructure;
- RTCCAL_DateTypeDef RTCCAL_DateStructure;
- RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWR, ENABLE);
- RCC_APB1PeriphClockCmd(RCC_APB1ENR_BKP, ENABLE);
- PWR_BackupAccessCmd(ENABLE);
- RCC_LSEConfig(RCC_LSE_ON);
- while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
- RCC_APB1PeriphClockCmd(RCC_APB1ENR_RTC, ENABLE);
- RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
- RCC_RTCCLKCmd(ENABLE);
- RTCCAL_EnterInitMode();
- RTCCAL_WaitForSynchro();
- RTCCAL_StructInit(&RTCCAL_InitStructure);
- RTCCAL_InitStructure.RTCCAL_HourFormat = RTCCAL_HourFormat_24;
- RTCCAL_InitStructure.RTCCAL_AsynchPrediv = 0x7F;
- RTCCAL_InitStructure.RTCCAL_SynchPrediv = 0xFF;
- RTCCAL_Init(&RTCCAL_InitStructure);
- RTC_LoadDefault(&RTCCAL_DateStructure, &RTCCAL_TimeStructure);
- RTCCAL_TimeStructure.RTCCAL_H12 = RTCCAL_H12_AM;
- RTCCAL_SetTime(RTCCAL_Format_BIN, &RTCCAL_TimeStructure);
- RTCCAL_SetDate(RTCCAL_Format_BIN, &RTCCAL_DateStructure);
- RTCCAL_WaitForSynchro();
- RTCCAL_ExitInitMode();
- MultiTimerStart(&RTC_MultiTimer, 500, RTC_MultiTimerCallback, "RTC");
- }
- #endif
I2S & DMA & WAV功能实现: - #if ENABLE_I2S
- /* Private typedef -----------------------------------------------------------*/
- /* Private define ------------------------------------------------------------*/
- /* Private macro -------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- MultiTimer I2S_MultiTimer;
- /* Private variables ---------------------------------------------------------*/
- uint8_t WAV_DataBuffer[2][WAV_BUFFER_SIZE];
- uint8_t WAV_NextIndex = 0;
- uint8_t WAV_PlayEnded = 0;
- uint8_t WAV_PlayState = 0;
- /* Private variables ---------------------------------------------------------*/
- uint32_t WAV_Offset = 0;
- uint32_t WAV_DataSize = 0;
- uint32_t WAV_TxLength = 0;
- /* Private function prototypes -----------------------------------------------*/
- /* Private functions ---------------------------------------------------------*/
- /* Exported variables --------------------------------------------------------*/
- /* Exported function prototypes ----------------------------------------------*/
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void I2S_MultiTimerCallback(MultiTimer *timer, void *userData)
- {
- WAV_PlaySong();
- MultiTimerStart(&I2S_MultiTimer, 5000, I2S_MultiTimerCallback, "I2S");
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void mI2S_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- I2S_InitTypeDef I2S_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2ENR_SPI1, ENABLE);
- I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
- I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
- I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
- I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
- I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_44k;
- I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
- I2S_Init(SPI1, &I2S_InitStructure);
- SPI_DMACmd(SPI1, ENABLE);
- I2S_Cmd(SPI1, ENABLE);
- SPI1->GCTL |= (SPI_GCR_SPIEN | SPI_GCR_MODE | SPI_GCR_TXEN);
- RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOC, ENABLE);
- GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_6);
- GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_6);
- GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_6);
- GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_6);
- GPIO_StructInit(&GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 |
- GPIO_Pin_6 | GPIO_Pin_7;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
- GPIO_StructInit(&GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
- GPIO_WriteBit(GPIOC, GPIO_Pin_2, Bit_RESET);
- MultiTimerStart(&I2S_MultiTimer, 5000, I2S_MultiTimerCallback, "I2S");
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void I2S_DMA_Transfer(uint16_t *Buffer, uint32_t BufferSize)
- {
- DMA_InitTypeDef DMA_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- DMA_DeInit(DMA1_Channel1);
- RCC_AHBPeriphClockCmd(RCC_AHBENR_DMA1, ENABLE);
- DMA_StructInit(&DMA_InitStructure);
- DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->TXREG);
- DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Buffer;
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
- DMA_InitStructure.DMA_BufferSize = BufferSize;
- 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_HalfWord;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
- DMA_InitStructure.DMA_Auto_reload = DMA_Auto_Reload_Disable;
- DMA_Init(DMA1_Channel1, &DMA_InitStructure);
- if(DMA_InitStructure.DMA_PeripheralBaseAddr == ((uint32_t)(&(SPI1->TXREG))))
- {
- DMA_SetChannelMuxSource(DMA1_Channel1, DMA1_MUX_SPI1_TX);
- if(DMA_GetChannelMuxSource(DMA1_Channel1) != DMA1_MUX_SPI1_TX)
- {
- while(1);
- }
- }
- NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
- DMA_ITConfig(DMA1_Channel1, DMA_IT_HT, ENABLE);
- DMA_Cmd(DMA1_Channel1, ENABLE);
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- uint8_t WAV_DecodeFile(WAV_TypeDef *pWav, uint32_t Address)
- {
- ChunkRIFF_TypeDef *WAV_RIFF;
- ChunkFMT_TypeDef *WAV_FMT ;
- ChunkFACT_TypeDef *WAV_FACT;
- ChunkDATA_TypeDef *WAV_DATA;
- uint8_t WAV_HeadBuffer[512];
- SPI_FLASH_FastRead(Address, WAV_HeadBuffer, 512);
- /* 获取RIFF块 */
- WAV_RIFF = (ChunkRIFF_TypeDef *)WAV_HeadBuffer;
- /* 是WAV格式文件 */
- if(WAV_RIFF->Format == 0x45564157)
- {
- /* 获取FMT块 */
- WAV_FMT = (ChunkFMT_TypeDef *)(WAV_HeadBuffer+12);
- /* 读取FACT块 */
- WAV_FACT = (ChunkFACT_TypeDef *)(WAV_HeadBuffer+12+8+WAV_FMT->ChunkSize);
- if((WAV_FACT->ChunkID == 0x74636166) || (WAV_FACT->ChunkID == 0x5453494C))
- {
- /* 具有FACT/LIST块的时候(未测试) */
- pWav->DataStart=12+8+WAV_FMT->ChunkSize+8+WAV_FACT->ChunkSize;
- }
- else
- {
- pWav->DataStart=12+8+WAV_FMT->ChunkSize;
- }
- /* 读取DATA块 */
- WAV_DATA = (ChunkDATA_TypeDef *)(WAV_HeadBuffer+pWav->DataStart);
- /* 解析成功 */
- if(WAV_DATA->ChunkID == 0x61746164)
- {
- pWav->AudioFormat = WAV_FMT->AudioFormat; /* 音频格式 */
- pWav->nChannels = WAV_FMT->NumOfChannels; /* 通道数 */
- pWav->SampleRate = WAV_FMT->SampleRate; /* 采样率 */
- pWav->BitRate = WAV_FMT->ByteRate*8; /* 得到位速 */
- pWav->BlockAlign = WAV_FMT->BlockAlign; /* 块对齐 */
- pWav->BitsPerSample = WAV_FMT->BitsPerSample; /* 位数,16/24/32位 */
- pWav->DataSize = WAV_DATA->ChunkSize; /* 数据块大小 */
- pWav->DataStart = pWav->DataStart+8; /* 数据流开始的地方 */
- printf("\r\npWav->AudioFormat : %d", pWav->AudioFormat);
- printf("\r\npWav->nChannels : %d", pWav->nChannels);
- printf("\r\npWav->SampleRate : %d", pWav->SampleRate);
- printf("\r\npWav->BitRate : %d", pWav->BitRate);
- printf("\r\npWav->BlockAlign : %d", pWav->BlockAlign);
- printf("\r\npWav->BitsPerSample : %d", pWav->BitsPerSample);
- printf("\r\npWav->DataSize : %d", pWav->DataSize);
- printf("\r\npWav->DataStart : %d", pWav->DataStart);
- WAV_Offset = pWav->DataStart + Address;
- WAV_DataSize = pWav->DataSize;
- }
- }
- return 0;
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void WAV_PrepareData(void)
- {
- if(WAV_NextIndex == 0)
- {
- SPI_FLASH_FastRead(WAV_Offset + WAV_TxLength, WAV_DataBuffer[0], WAV_BUFFER_SIZE);
- }
- else
- {
- SPI_FLASH_FastRead(WAV_Offset + WAV_TxLength, WAV_DataBuffer[1], WAV_BUFFER_SIZE);
- }
- WAV_TxLength += WAV_BUFFER_SIZE;
- if(WAV_TxLength > WAV_DataSize) WAV_PlayEnded = 1;
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void WAV_PlayHandler(void)
- {
- if(WAV_PlayEnded == 0)
- {
- I2S_DMA_Transfer((uint16_t *)&WAV_DataBuffer[WAV_NextIndex][0], (WAV_BUFFER_SIZE / 2));
- }
- else
- {
- DMA_Cmd(DMA1_Channel1, DISABLE);
- printf("\r\nWAV Play Finish!\r\n"); WAV_PlayState = 0;
- }
- if(WAV_NextIndex == 0) WAV_NextIndex = 1;
- else WAV_NextIndex = 0;
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- 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");
- }
- }
- /*******************************************************************************
- * @brief
- * @param
- * @retval
- * @attention
- *******************************************************************************/
- void DMA1_Channel1_IRQHandler(void)
- {
- if(DMA_GetITStatus(DMA1_IT_TC1) != RESET)
- {
- DMA_ClearITPendingBit(DMA1_IT_TC1);
- WAV_PlayHandler();
- }
- if(DMA_GetITStatus(DMA1_IT_HT1) != RESET)
- {
- DMA_ClearITPendingBit(DMA1_IT_HT1);
- WAV_PrepareData();
- }
- }
- #endif
还有其它等等功能,由于篇幅太长就不这边一一列举出来,大家可以下载最后的软件工程源代码进行学习和研究。
软件工程源代码 最后我们附上完整的软件工程源代码,供大家下载学习!!!
|