12下一页
返回列表 发新帖我要提问本帖赏金: 100.00元(功能说明)

[MM32生态] EVB-L0136开发学习分享

[复制链接]
 楼主| xld0932 发表于 2022-11-2 16:06 | 显示全部楼层 |阅读模式
<
#申请原创#   @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数据线
1.jpg
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显示屏……


准备相关资料
MM32L0130数据手册: DS_MM32L0130_SC.pdf (2.36 MB, 下载次数: 36)
MM32L0130用户手册: UM_MM32L0130_SC.pdf (12.53 MB, 下载次数: 142)
MM32L0130 KEIL芯片支持包: MindMotion.MM32L0130_DFP.0.0.2.pack.zip (36.45 KB, 下载次数: 29)
EVB-L0130开发析用户手册: UG_EVB-L0136_SC.pdf (1.17 MB, 下载次数: 32)
EVB-L0130开发板原理图: EVB-L0136_SCH.pdf (575.08 KB, 下载次数: 35)
MM32L0130 MindSDK驱动程序: Windows mdk_evb-l0130 2022-08-15 1033.zip (9.04 MB, 下载次数: 53)
MM32L0130 LibSample驱动程序: MM32L0130_LibSamples_V020.zip (4.19 MB, 下载次数: 53)
段码LCD显示屏手册: GDC0689TP-11.pdf (896.84 KB, 下载次数: 50)


实现功能
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功能实现:
  1. #if ENABLE_ADC


  2. /* Private typedef -----------------------------------------------------------*/
  3. /* Private define ------------------------------------------------------------*/
  4. /* Private macro -------------------------------------------------------------*/


  5. /* Private variables ---------------------------------------------------------*/
  6. MultiTimer ADC_MultiTimer;


  7. /* Private variables ---------------------------------------------------------*/
  8. float RV1_Voltage = 0.0;
  9. float RV2_Voltage = 0.0;
  10. float RV3_Voltage = 0.0;


  11. /* Private variables ---------------------------------------------------------*/
  12. uint16_t ADC_Flag  =  0;
  13. uint16_t ADC_Buffer[30];


  14. /* Private function prototypes -----------------------------------------------*/
  15. /* Private functions ---------------------------------------------------------*/


  16. /* Exported variables --------------------------------------------------------*/
  17. /* Exported function prototypes ----------------------------------------------*/


  18. /*******************************************************************************
  19. * [url=home.php?mod=space&uid=247401]@brief[/url]      
  20. * @param      
  21. * @retval      
  22. * [url=home.php?mod=space&uid=93590]@Attention[/url]   
  23. *******************************************************************************/
  24. void ADC_MultiTimerCallback(MultiTimer *timer, void *userData)
  25. {
  26.     uint32_t ADC0_Value = 0;
  27.     uint32_t ADC1_Value = 0;
  28.     uint32_t ADC2_Value = 0;

  29.     if(ADC_Flag == 1)
  30.     {
  31.         ADC_Flag = 0;

  32.         for(uint8_t i = 0; i < 30;)
  33.         {
  34.             ADC0_Value += ADC_Buffer[i++];
  35.             ADC1_Value += ADC_Buffer[i++];
  36.             ADC2_Value += ADC_Buffer[i++];
  37.         }

  38.         RV1_Voltage = ((float)(ADC0_Value) / 4096.0) * 3.3 / 10.0;
  39.         RV2_Voltage = ((float)(ADC1_Value) / 4096.0) * 3.3 / 10.0;
  40.         RV3_Voltage = ((float)(ADC2_Value) / 4096.0) * 3.3 / 10.0;

  41.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);
  42.     }

  43.     MultiTimerStart(&ADC_MultiTimer, 250, ADC_MultiTimerCallback, "ADC");
  44. }


  45. /*******************************************************************************
  46. * @brief      
  47. * @param      
  48. * @retval      
  49. * @attention   
  50. *******************************************************************************/
  51. void mADC_Init(void)
  52. {
  53.     ADC_InitTypeDef  ADC_InitStructure;
  54.     DMA_InitTypeDef  DMA_InitStruct;
  55.     GPIO_InitTypeDef GPIO_InitStructure;
  56.     NVIC_InitTypeDef NVIC_InitStruct;

  57.     RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);

  58.     GPIO_StructInit(&GPIO_InitStructure);
  59.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5;
  60.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  61.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AIN;
  62.     GPIO_Init(GPIOA, &GPIO_InitStructure);

  63.     NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel1_IRQn;
  64.     NVIC_InitStruct.NVIC_IRQChannelPriority = 2;
  65.     NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  66.     NVIC_Init(&NVIC_InitStruct);

  67.     RCC_AHBPeriphClockCmd(RCC_AHBENR_DMA1, ENABLE);

  68.     DMA_DeInit(DMA1_Channel1);

  69.     DMA_StructInit(&DMA_InitStruct);
  70.     DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR);
  71.     DMA_InitStruct.DMA_MemoryBaseAddr     = (uint32_t)&ADC_Buffer;
  72.     DMA_InitStruct.DMA_DIR                = DMA_DIR_PeripheralSRC;
  73.     DMA_InitStruct.DMA_BufferSize         = 30;
  74.     DMA_InitStruct.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
  75.     DMA_InitStruct.DMA_MemoryInc          = DMA_MemoryInc_Enable;
  76.     DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  77.     DMA_InitStruct.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;
  78.     DMA_InitStruct.DMA_Mode               = DMA_Mode_Circular;
  79.     DMA_InitStruct.DMA_Priority           = DMA_Priority_High;
  80.     DMA_InitStruct.DMA_M2M                = DMA_M2M_Disable;
  81.     DMA_InitStruct.DMA_Auto_reload        = DMA_Auto_Reload_Disable;
  82.     DMA_Init(DMA1_Channel1, &DMA_InitStruct);

  83.     if(DMA_InitStruct.DMA_PeripheralBaseAddr == ((uint32_t)(&ADC1->DR)))
  84.     {
  85.         DMA_SetChannelMuxSource(DMA1_Channel1, DMA1_MUX_ADC1);

  86.         if(DMA_GetChannelMuxSource(DMA1_Channel1) != DMA1_MUX_ADC1)
  87.         {
  88.             while(1);
  89.         }
  90.     }

  91.     DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
  92.     DMA_Cmd(DMA1_Channel1, ENABLE);

  93.     RCC_APB2PeriphClockCmd(RCC_APB2ENR_ADC1, ENABLE);

  94.     ADC_StructInit(&ADC_InitStructure);
  95.     ADC_InitStructure.ADC_Resolution         = ADC_Resolution_12b;
  96.     ADC_InitStructure.ADC_PRESCARE           = ADC_PCLK2_PRESCARE_16;
  97.     ADC_InitStructure.ADC_Mode               = ADC_Mode_Continue;
  98.     ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  99.     ADC_InitStructure.ADC_ExternalTrigConv   = ADC1_ExternalTrigConv_T3_CC3;
  100.     ADC_InitStructure.ADC_DataAlign          = ADC_DataAlign_Right;
  101.     ADC_Init(ADC1, &ADC_InitStructure);

  102.     ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 0, ADC_Samctl_240_5);
  103.     ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_Samctl_240_5);
  104.     ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2, ADC_Samctl_240_5);

  105.     ADC_DMACmd(ADC1, ENABLE);
  106.     ADC_Cmd(ADC1, ENABLE);

  107.     ADC_SoftwareStartConvCmd(ADC1, ENABLE);

  108.     MultiTimerStart(&ADC_MultiTimer, 250, ADC_MultiTimerCallback, "ADC");
  109. }


  110. /*******************************************************************************
  111. * @brief      
  112. * @param      
  113. * @retval      
  114. * @attention   
  115. *******************************************************************************/
  116. void DMA1_Channel1_IRQHandler(void)
  117. {
  118.     ADC_SoftwareStartConvCmd(ADC1, DISABLE);
  119.     DMA_ClearITPendingBit(DMA1_IT_TC1);
  120.     ADC_Flag = 1;
  121. }


  122. #endif


BUZZER & TIM & PWM功能实现:
  1. #if ENABLE_BUZZER


  2. /* Private typedef -----------------------------------------------------------*/
  3. /* Private define ------------------------------------------------------------*/
  4. /* Private macro -------------------------------------------------------------*/


  5. /* Private variables ---------------------------------------------------------*/
  6. MultiTimer BUZZER_MultiTimer;


  7. /* Private variables ---------------------------------------------------------*/
  8. BUZZER_TypeDef BUZZER_TAB[] =
  9. {
  10.     {50, 100, 1},
  11.     {50, 100, 1},
  12.     {50, 100, 0},
  13. };


  14. /* Private variables ---------------------------------------------------------*/
  15. volatile uint8_t BUZZER_Flag = 0;


  16. /* Private function prototypes -----------------------------------------------*/
  17. /* Private functions ---------------------------------------------------------*/


  18. /* Exported variables --------------------------------------------------------*/
  19. /* Exported function prototypes ----------------------------------------------*/


  20. #if 1


  21. /*******************************************************************************
  22. * @brief      
  23. * @param      
  24. * @retval      
  25. * @attention   
  26. *******************************************************************************/
  27. void BUZZER_MultiTimerCallback(MultiTimer *timer, void *userData)
  28. {
  29.     static uint8_t State = 0, Index = 0;

  30.     if(State == 0)
  31.     {
  32.         State = 1;  BUZZER_Flag = 1;

  33.         MultiTimerStart(&BUZZER_MultiTimer, BUZZER_TAB[Index].PlayMS, BUZZER_MultiTimerCallback, "BUZZER");
  34.     }
  35.     else
  36.     {
  37.         State = 0;  BUZZER_Flag = 0;

  38.         if(BUZZER_TAB[Index].KeepOn)
  39.         {
  40.             MultiTimerStart(&BUZZER_MultiTimer, BUZZER_TAB[Index++].WaitMS, BUZZER_MultiTimerCallback, "BUZZER");
  41.         }
  42.         else
  43.         {
  44.             Index = 0;
  45.         }
  46.     }
  47. }


  48. /*******************************************************************************
  49. * @brief      
  50. * @param      
  51. * @retval      
  52. * @attention   
  53. *******************************************************************************/
  54. void BUZZER_Init(void)
  55. {
  56.     GPIO_InitTypeDef        GPIO_InitStructure;
  57.     NVIC_InitTypeDef        NVIC_InitStructure;
  58.     TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

  59.     RCC_ClocksTypeDef  RCC_Clocks;
  60.     RCC_GetClocksFreq(&RCC_Clocks);

  61.     RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);

  62.     GPIO_StructInit(&GPIO_InitStructure);
  63.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6;
  64.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  65.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
  66.     GPIO_Init(GPIOA, &GPIO_InitStructure);

  67.     NVIC_InitStructure.NVIC_IRQChannel = TIM16_IRQn;
  68.     NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
  69.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  70.     NVIC_Init(&NVIC_InitStructure);

  71.     RCC_APB2PeriphClockCmd(RCC_APB2ENR_TIM16, ENABLE);

  72.     TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  73.     TIM_TimeBaseStructure.TIM_Prescaler         = (RCC_Clocks.SYSCLK_Frequency / 1000000 - 1);
  74.     TIM_TimeBaseStructure.TIM_ClockDivision     = TIM_CKD_DIV1;
  75.     TIM_TimeBaseStructure.TIM_Period            = (500 - 1);
  76.     TIM_TimeBaseStructure.TIM_CounterMode       = TIM_CounterMode_Up;
  77.     TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  78.     TIM_TimeBaseInit(TIM16, &TIM_TimeBaseStructure);

  79.     TIM_ITConfig(TIM16, TIM_IT_Update, ENABLE);

  80.     TIM_Cmd(TIM16, ENABLE);

  81.     MultiTimerStart(&BUZZER_MultiTimer, 100, BUZZER_MultiTimerCallback, "BUZZER");
  82. }


  83. /*******************************************************************************
  84. * @brief      
  85. * @param      
  86. * @retval      
  87. * @attention   
  88. *******************************************************************************/
  89. void TIM16_IRQHandler(void)
  90. {
  91.     static BitAction Value = Bit_RESET;

  92.     if(TIM_GetITStatus(TIM16, TIM_IT_Update) != RESET)
  93.     {
  94.         if(BUZZER_Flag == 1)
  95.         {
  96.             if(Value == Bit_RESET)  Value = Bit_SET;
  97.             else                    Value = Bit_RESET;

  98.             GPIO_WriteBit(GPIOA, GPIO_Pin_6, Value);
  99.         }

  100.         TIM_ClearITPendingBit(TIM16, TIM_IT_Update);
  101.     }
  102. }


  103. #else


  104. /*******************************************************************************
  105. * @brief      
  106. * @param      
  107. * @retval      
  108. * @attention   
  109. *******************************************************************************/
  110. void BUZZER_MultiTimerCallback(MultiTimer *timer, void *userData)
  111. {
  112.     static uint8_t State = 0, Index = 0;

  113.     if(State == 0)
  114.     {
  115.         State = 1;  TIM_SetCompare1(TIM3, 500);

  116.         MultiTimerStart(&BUZZER_MultiTimer, BUZZER_TAB[Index].PlayMS, BUZZER_MultiTimerCallback, "BUZZER");
  117.     }
  118.     else
  119.     {
  120.         State = 0;  TIM_SetCompare1(TIM3, 0);

  121.         if(BUZZER_TAB[Index].KeepOn)
  122.         {
  123.             MultiTimerStart(&BUZZER_MultiTimer, BUZZER_TAB[Index++].WaitMS, BUZZER_MultiTimerCallback, "BUZZER");
  124.         }
  125.         else
  126.         {
  127.             Index = 0;
  128.         }
  129.     }
  130. }


  131. /*******************************************************************************
  132. * @brief      
  133. * @param      
  134. * @retval      
  135. * @attention   
  136. *******************************************************************************/
  137. void BUZZER_Init(void)
  138. {
  139.     GPIO_InitTypeDef        GPIO_InitStructure;
  140.     TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  141.     TIM_OCInitTypeDef       TIM_OCInitStructure;

  142.     RCC_ClocksTypeDef  RCC_Clocks;
  143.     RCC_GetClocksFreq(&RCC_Clocks);

  144.     RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);

  145.     GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_1);

  146.     GPIO_StructInit(&GPIO_InitStructure);
  147.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6;
  148.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  149.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
  150.     GPIO_Init(GPIOA, &GPIO_InitStructure);

  151.     RCC_APB1PeriphClockCmd(RCC_APB1ENR_TIM3, ENABLE);

  152.     TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  153.     TIM_TimeBaseStructure.TIM_Prescaler         = (RCC_Clocks.PCLK1_Frequency / 1000000 - 1);
  154.     TIM_TimeBaseStructure.TIM_ClockDivision     = TIM_CKD_DIV1;
  155.     TIM_TimeBaseStructure.TIM_Period            = (1000 - 1);
  156.     TIM_TimeBaseStructure.TIM_CounterMode       = TIM_CounterMode_Up;
  157.     TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  158.     TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  159.     TIM_OCStructInit(&TIM_OCInitStructure);
  160.     TIM_OCInitStructure.TIM_OCMode       = TIM_OCMode_PWM2;
  161.     TIM_OCInitStructure.TIM_OutputState  = TIM_OutputState_Enable;
  162.     TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
  163.     TIM_OCInitStructure.TIM_Pulse        = 0;
  164.     TIM_OCInitStructure.TIM_OCPolarity   = TIM_OCPolarity_High;
  165.     TIM_OC1Init(TIM3, &TIM_OCInitStructure);

  166.     TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
  167.     TIM_ARRPreloadConfig(TIM3, ENABLE);

  168.     TIM_Cmd(TIM3, ENABLE);

  169.     TIM_CtrlPWMOutputs(TIM3, ENABLE);

  170.     MultiTimerStart(&BUZZER_MultiTimer, 100, BUZZER_MultiTimerCallback, "BUZZER");
  171. }


  172. #endif


  173. #endif


EEPROM & I2C功能实现:
  1. #if ENABLE_EEPROM


  2. /* Private typedef -----------------------------------------------------------*/
  3. /* Private define ------------------------------------------------------------*/
  4. /* Private macro -------------------------------------------------------------*/
  5. /* Private variables ---------------------------------------------------------*/
  6. /* Private function prototypes -----------------------------------------------*/
  7. /* Private functions ---------------------------------------------------------*/


  8. /* Exported variables --------------------------------------------------------*/
  9. /* Exported function prototypes ----------------------------------------------*/


  10. /*******************************************************************************
  11. * @brief      
  12. * @param      
  13. * @retval      
  14. * @attention   
  15. *******************************************************************************/
  16. void I2C_GetBuffer(uint8_t Address, uint8_t *Buffer, uint8_t Length)
  17. {
  18.     uint8_t Flag = 0, Count = 0;

  19.     I2C_SendData(I2C1, Address);
  20.     while(!I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE));

  21.     for(uint8_t i = 0; i < Length; i++)
  22.     {
  23.         while(1)
  24.         {
  25.             if((I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFNF)) && (Flag == 0))
  26.             {
  27.                 I2C_ReadCmd(I2C1);   Count++;
  28.                 if(Count == Length) Flag = 1;
  29.             }

  30.             if(I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_RFNE))
  31.             {
  32.                 Buffer[i] = I2C_ReceiveData(I2C1);     break;
  33.             }
  34.         }
  35.     }

  36.     I2C_GenerateSTOP(I2C1, ENABLE);
  37.     while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_STOP_DET));
  38. }


  39. /*******************************************************************************
  40. * @brief      
  41. * @param      
  42. * @retval      
  43. * @attention   
  44. *******************************************************************************/
  45. void I2C_PutBuffer(uint8_t Address, uint8_t *Buffer, uint8_t Length)
  46. {
  47.     I2C_SendData(I2C1, Address);
  48.     while(!I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE));

  49.     for(uint8_t i = 0; i < Length; i++)
  50.     {
  51.         I2C_SendData(I2C1, *Buffer++);
  52.         while(!I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE));
  53.     }

  54.     I2C_GenerateSTOP(I2C1, ENABLE);
  55.     while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_STOP_DET));
  56. }


  57. /*******************************************************************************
  58. * @brief      
  59. * @param      
  60. * @retval      
  61. * @attention   
  62. *******************************************************************************/
  63. void EEPROM_ReadData(uint8_t Address, uint8_t *Buffer, uint8_t Length)
  64. {
  65.     I2C_GetBuffer(Address, Buffer, Length);
  66. }


  67. /*******************************************************************************
  68. * @brief      
  69. * @param      
  70. * @retval      
  71. * @attention   
  72. *******************************************************************************/
  73. void EEPROM_WriteData(uint8_t Address, uint8_t *Buffer, uint8_t Length)
  74. {
  75.     uint8_t Start, StartCount, PageNumber, FinalCount;

  76.     if((Address % EEPROM_PAGE_SIZE) == 0)
  77.     {
  78.         StartCount = 0;
  79.         PageNumber = Length / EEPROM_PAGE_SIZE;
  80.         FinalCount = Length % EEPROM_PAGE_SIZE;
  81.     }
  82.     else
  83.     {
  84.         Start = Address % EEPROM_PAGE_SIZE;

  85.         if(((Start + Length) / EEPROM_PAGE_SIZE) == 0)
  86.         {
  87.             StartCount = Length;
  88.             PageNumber = 0;
  89.             FinalCount = 0;
  90.         }
  91.         else
  92.         {
  93.             StartCount = EEPROM_PAGE_SIZE - Start;
  94.             PageNumber = (Length - StartCount) / EEPROM_PAGE_SIZE;
  95.             FinalCount = (Length - StartCount) % EEPROM_PAGE_SIZE;
  96.         }
  97.     }

  98.     if(StartCount)
  99.     {
  100.         I2C_PutBuffer(Address, Buffer, StartCount);
  101.         Address += StartCount;
  102.         Buffer  += StartCount;

  103.         printf("\r\nWait A Moument...");    SysTick_DelayMS(10);
  104.     }

  105.     while(PageNumber--)
  106.     {
  107.         I2C_PutBuffer(Address, Buffer, EEPROM_PAGE_SIZE);

  108.         Address += EEPROM_PAGE_SIZE;
  109.         Buffer  += EEPROM_PAGE_SIZE;

  110.         printf("\r\nWait A Moument...");    SysTick_DelayMS(10);
  111.     }

  112.     if(FinalCount)
  113.     {
  114.         I2C_PutBuffer(Address, Buffer, FinalCount);
  115.     }
  116. }


  117. /*******************************************************************************
  118. * @brief      
  119. * @param      
  120. * @retval      
  121. * @attention   
  122. *******************************************************************************/
  123. void EEPROM_Init(void)
  124. {
  125.     GPIO_InitTypeDef GPIO_InitStructure;
  126.     I2C_InitTypeDef  I2C_InitStructure;

  127.     RCC_APB1PeriphClockCmd(RCC_APB1ENR_I2C1, ENABLE);

  128.     I2C_StructInit(&I2C_InitStructure);
  129.     I2C_InitStructure.I2C_Mode       = I2C_Mode_MASTER;
  130.     I2C_InitStructure.I2C_OwnAddress = 0;
  131.     I2C_InitStructure.I2C_Speed      = I2C_Speed_STANDARD;
  132.     I2C_InitStructure.I2C_ClockSpeed = 100000;
  133.     I2C_Init(I2C1, &I2C_InitStructure);

  134.     I2C_Send7bitAddress(I2C1, EEPROM_I2C_ADDRESS, I2C_Direction_Transmitter);

  135.     I2C_Cmd(I2C1, ENABLE);

  136.     RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOB, ENABLE);

  137.     GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_3);
  138.     GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_3);

  139.     GPIO_StructInit(&GPIO_InitStructure);
  140.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10 | GPIO_Pin_11;
  141.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  142.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_OD;
  143.     GPIO_Init(GPIOB, &GPIO_InitStructure);
  144. }


  145. /*******************************************************************************
  146. * @brief      
  147. * @param      
  148. * @retval      
  149. * @attention   
  150. *******************************************************************************/
  151. void EEPROM_Demo(void)
  152. {
  153.     uint8_t rBuffer[20], wBuffer[20];
  154.     uint8_t Address = 0;
  155.     uint8_t Length = 20;

  156.     for(uint8_t i = 0; i < Length; i++)
  157.     {
  158.         rBuffer[i] = 0;
  159.         wBuffer[i] = i;
  160.     }

  161.     printf("\r\n\r\nEEPROM Write Data : ");

  162.     EEPROM_WriteData(Address, wBuffer, Length);

  163.     printf("OK");   SysTick_DelayMS(10);

  164.     printf("\r\n\r\nEEPROM Read  Data : \r\n");

  165.     EEPROM_ReadData(Address, rBuffer, Length);

  166.     for(uint8_t i = 0; i < Length; i++)
  167.     {
  168.         printf("0x%02x ", rBuffer[i]);

  169.         if(((i + 1) % 10) == 0) printf("\r\n");
  170.     }

  171.     printf("\r\n\r\n");
  172. }


  173. #endif


SPI FLASH & SFUD功能实现:
  1. /* Includes ------------------------------------------------------------------*/
  2. #include <sfud.h>


  3. /* Private typedef -----------------------------------------------------------*/


  4. /* Private define ------------------------------------------------------------*/
  5. #define SFUD_DEMO_BUFFER_SIZE      (512)


  6. /* Private macro -------------------------------------------------------------*/


  7. /* Private variables ---------------------------------------------------------*/
  8. uint8_t sfud_demo_buf[SFUD_DEMO_BUFFER_SIZE];


  9. /* Private function prototypes -----------------------------------------------*/
  10. /* Private functions ---------------------------------------------------------*/


  11. /* Exported variables --------------------------------------------------------*/
  12. /* Exported function prototypes ----------------------------------------------*/


  13. /*******************************************************************************
  14. * @brief       SFUD demo for the first flash device test
  15. * @param       addr flash start address
  16. * @param       size test flash size
  17. * @param       size test flash data buffer
  18. * @retval      
  19. * @attention   
  20. *******************************************************************************/
  21. void sfud_demo(uint32_t addr, size_t size, uint8_t *data)
  22. {
  23.     sfud_err result = SFUD_SUCCESS;

  24.     const sfud_flash *flash = sfud_get_device_table() + 0;

  25.     size_t i;

  26.     /* prepare write data */
  27.     for(i = 0; i < size; i++)
  28.     {
  29.         data[i] = i;
  30.     }

  31.     /* erase test */
  32.     result = sfud_erase(flash, addr, size);

  33.     if(result == SFUD_SUCCESS)
  34.     {
  35.         printf("\r\nErase the %s flash data finish. Start from 0x%08X, size is %d.\r\n", flash->name, addr, size);
  36.     }
  37.     else
  38.     {
  39.         printf("\r\nErase the %s flash data failed.\r\n", flash->name);
  40.         return;
  41.     }

  42.     /* write test */
  43.     result = sfud_write(flash, addr, size, data);

  44.     if(result == SFUD_SUCCESS)
  45.     {
  46.         printf("\r\nWrite the %s flash data finish. Start from 0x%08X, size is %d.\r\n", flash->name, addr, size);
  47.     }
  48.     else
  49.     {
  50.         printf("\r\nWrite the %s flash data failed.\r\n", flash->name);
  51.         return;
  52.     }

  53.     /* read test */
  54.     result = sfud_read(flash, addr, size, data);

  55.     if(result == SFUD_SUCCESS)
  56.     {
  57.         printf("\r\nRead the %s flash data success. Start from 0x%08X, size is %d. The data is:\r\n", flash->name, addr, size);

  58.         printf("Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\r\n");

  59.         for(i = 0; i < size; i++)
  60.         {
  61.             if((i % 16) == 0)
  62.             {
  63.                 printf("[%08X] ", addr + i);
  64.             }

  65.             printf("%02X ", data[i]);

  66.             if(((i + 1) % 16 == 0) || (i == size - 1))
  67.             {
  68.                 printf("\r\n");
  69.             }
  70.         }

  71.         printf("\r\n");
  72.     }
  73.     else
  74.     {
  75.         printf("\r\nRead the %s flash data failed.\r\n", flash->name);
  76.     }

  77.     /* data check */
  78.     for(i = 0; i < size; i++)
  79.     {
  80.         if(data[i] != i % 256)
  81.         {
  82.             printf("\r\nRead and check write data has an error. Write the %s flash data failed.\r\n", flash->name);
  83.             break;
  84.         }
  85.     }

  86.     if(i == size)
  87.     {
  88.         printf("\r\nThe %s flash test is success.\r\n", flash->name);
  89.     }
  90. }


  91. /*******************************************************************************
  92. * @brief      
  93. * @param      
  94. * @retval      
  95. * @attention   
  96. *******************************************************************************/
  97. void SPI_FLASH_Init(void)
  98. {
  99.     printf("\r\n");

  100.     if(sfud_init() == SFUD_SUCCESS)
  101.     {
  102.         sfud_demo(0, sizeof(sfud_demo_buf), sfud_demo_buf);
  103.     }
  104. }


RTC & LCD功能实现:
  1. #if ENABLE_RTC


  2. /* Private typedef -----------------------------------------------------------*/
  3. /* Private define ------------------------------------------------------------*/
  4. /* Private macro -------------------------------------------------------------*/


  5. /* Private variables ---------------------------------------------------------*/
  6. MultiTimer RTC_MultiTimer;


  7. /* Private function prototypes -----------------------------------------------*/
  8. /* Private functions ---------------------------------------------------------*/


  9. /* Exported variables --------------------------------------------------------*/
  10. /* Exported function prototypes ----------------------------------------------*/


  11. /*******************************************************************************
  12. * @brief      
  13. * @param      
  14. * @retval      
  15. * @attention   
  16. *******************************************************************************/
  17. uint8_t RTC_GetWeek(uint16_t Year, uint8_t Month, uint8_t Day)
  18. {
  19.     int w, c, y;

  20.     /* Month 1 Or 2 of This Year Must Be As Last Month 13 Or 14 */
  21.     if((Month == 1) || (Month == 2))
  22.     {
  23.         Month += 12;
  24.         Year  -= 1;
  25.     }

  26.     w = 0;          /* Weekday */
  27.     c = Year / 100; /* Century */
  28.     y = Year % 100; /* Year    */

  29.     w = y + (y / 4) + (c / 4) - (2 * c) + (26 * (Month + 1) / 10) + Day - 1;

  30.     while(w < 0) w += 7;

  31.     w %= 7;

  32.     return w;
  33. }


  34. /*******************************************************************************
  35. * @brief      
  36. * @param      
  37. * @retval      
  38. * @attention   
  39. *******************************************************************************/
  40. void RTC_LoadDefault(RTCCAL_DateTypeDef *RTCCAL_Date, RTCCAL_TimeTypeDef *RTCCAL_Time)
  41. {
  42.     char    date[20], time[20];
  43.     char    text[6][5];
  44.     uint8_t index = 0, month = 0;

  45.     memset(date, 0, sizeof(date));
  46.     memset(time, 0, sizeof(time));
  47.     memset(text, 0, sizeof(text));

  48.     memcpy(date, __DATE__, sizeof(__DATE__));
  49.     memcpy(time, __TIME__, sizeof(__TIME__));

  50.     char *str;

  51.     str = strtok(date, " ");

  52.     while(str != NULL)
  53.     {
  54.         memcpy(text[index], str, strlen(str));
  55.         index++;

  56.         str = strtok(NULL, " ");
  57.     }

  58.     str = strtok(time, ":");

  59.     while(str != NULL)
  60.     {
  61.         memcpy(text[index], str, strlen(str));
  62.         index++;

  63.         str = strtok(NULL, ":");
  64.     }

  65. #if 0
  66.     for(uint8_t i = 0; i < index; i++)
  67.     {
  68.         printf("\r\n->%s", text[i]);
  69.     }
  70. #endif

  71.     char *strMonth[12] =
  72.     {
  73.         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  74.         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
  75.     };

  76.     for(uint8_t i = 0; i < 12; i++)
  77.     {
  78.         if(strcmp(text[0], strMonth[i]) == 0)
  79.         {
  80.             month = i + 1;
  81.         }
  82.     }

  83.     RTCCAL_Date->RTCCAL_Date    = atoi(text[1]);
  84.     RTCCAL_Date->RTCCAL_Month   = month;
  85.     RTCCAL_Date->RTCCAL_Year    = atoi(text[2]) - 2000;
  86.     RTCCAL_Date->RTCCAL_WeekDay = RTC_GetWeek(RTCCAL_Date->RTCCAL_Year + 2000,
  87.                                               RTCCAL_Date->RTCCAL_Month,
  88.                                               RTCCAL_Date->RTCCAL_Date);

  89.     RTCCAL_Time->RTCCAL_Hours   = atoi(text[3]);
  90.     RTCCAL_Time->RTCCAL_Minutes = atoi(text[4]);
  91.     RTCCAL_Time->RTCCAL_Seconds = atoi(text[5]);
  92. }


  93. /*******************************************************************************
  94. * @brief      
  95. * @param      
  96. * @retval      
  97. * @attention   
  98. *******************************************************************************/
  99. void RTC_MultiTimerCallback(MultiTimer *timer, void *userData)
  100. {
  101.     RTCCAL_TimeTypeDef RTCCAL_TimeStructure;
  102.     RTCCAL_DateTypeDef RTCCAL_DateStructure;

  103.     RTCCAL_GetTime(RTCCAL_Format_BIN, &RTCCAL_TimeStructure);
  104.     RTCCAL_GetDate(RTCCAL_Format_BIN, &RTCCAL_DateStructure);

  105. #if ENABLE_LCD
  106.     LCD_DisplayNumber2(0, '0' + (RTCCAL_TimeStructure.RTCCAL_Hours   / 10), 0);
  107.     LCD_DisplayNumber2(1, '0' + (RTCCAL_TimeStructure.RTCCAL_Hours   % 10), 0);
  108.     LCD_DisplayNumber2(2, '0' + (RTCCAL_TimeStructure.RTCCAL_Minutes / 10), 0);
  109.     LCD_DisplayNumber2(3, '0' + (RTCCAL_TimeStructure.RTCCAL_Minutes % 10), 0);
  110.     LCD_DisplayNumber2(4, '0' + (RTCCAL_TimeStructure.RTCCAL_Seconds / 10), 0);
  111.     LCD_DisplayNumber2(5, '0' + (RTCCAL_TimeStructure.RTCCAL_Seconds % 10), 0);
  112. #else
  113.     printf("\r\n%04d-%02d-%02d", RTCCAL_DateStructure.RTCCAL_Year + 2000, RTCCAL_DateStructure.RTCCAL_Month,  RTCCAL_DateStructure.RTCCAL_Date);

  114.     switch(RTCCAL_DateStructure.RTCCAL_WeekDay)
  115.     {
  116.         case 0 : printf(" SUN "); break;
  117.         case 1 : printf(" MON "); break;
  118.         case 2 : printf(" TUE "); break;
  119.         case 3 : printf(" WED "); break;
  120.         case 4 : printf(" THU "); break;
  121.         case 5 : printf(" FRI "); break;
  122.         case 6 : printf(" SAT "); break;
  123.         default: break;
  124.     }

  125.     printf("%02d:%02d:%02d\r\n", RTCCAL_TimeStructure.RTCCAL_Hours, RTCCAL_TimeStructure.RTCCAL_Minutes, RTCCAL_TimeStructure.RTCCAL_Seconds);
  126. #endif

  127.     MultiTimerStart(&RTC_MultiTimer, 500, RTC_MultiTimerCallback, "RTC");
  128. }


  129. /*******************************************************************************
  130. * @brief      
  131. * @param      
  132. * @retval      
  133. * @attention   
  134. *******************************************************************************/
  135. void RTC_Init(void)
  136. {
  137.     RTCCAL_InitTypeDef RTCCAL_InitStructure;
  138.     RTCCAL_TimeTypeDef RTCCAL_TimeStructure;
  139.     RTCCAL_DateTypeDef RTCCAL_DateStructure;

  140.     RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWR, ENABLE);
  141.     RCC_APB1PeriphClockCmd(RCC_APB1ENR_BKP, ENABLE);
  142.     PWR_BackupAccessCmd(ENABLE);

  143.     RCC_LSEConfig(RCC_LSE_ON);
  144.     while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);

  145.     RCC_APB1PeriphClockCmd(RCC_APB1ENR_RTC, ENABLE);

  146.     RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
  147.     RCC_RTCCLKCmd(ENABLE);

  148.     RTCCAL_EnterInitMode();

  149.     RTCCAL_WaitForSynchro();

  150.     RTCCAL_StructInit(&RTCCAL_InitStructure);
  151.     RTCCAL_InitStructure.RTCCAL_HourFormat   = RTCCAL_HourFormat_24;
  152.     RTCCAL_InitStructure.RTCCAL_AsynchPrediv = 0x7F;
  153.     RTCCAL_InitStructure.RTCCAL_SynchPrediv  = 0xFF;
  154.     RTCCAL_Init(&RTCCAL_InitStructure);

  155.     RTC_LoadDefault(&RTCCAL_DateStructure, &RTCCAL_TimeStructure);
  156.     RTCCAL_TimeStructure.RTCCAL_H12 = RTCCAL_H12_AM;
  157.     RTCCAL_SetTime(RTCCAL_Format_BIN, &RTCCAL_TimeStructure);
  158.     RTCCAL_SetDate(RTCCAL_Format_BIN, &RTCCAL_DateStructure);

  159.     RTCCAL_WaitForSynchro();

  160.     RTCCAL_ExitInitMode();

  161.     MultiTimerStart(&RTC_MultiTimer, 500, RTC_MultiTimerCallback, "RTC");
  162. }


  163. #endif

I2S & DMA & WAV功能实现:
  1. #if ENABLE_I2S


  2. /* Private typedef -----------------------------------------------------------*/
  3. /* Private define ------------------------------------------------------------*/
  4. /* Private macro -------------------------------------------------------------*/


  5. /* Private variables ---------------------------------------------------------*/
  6. MultiTimer I2S_MultiTimer;


  7. /* Private variables ---------------------------------------------------------*/
  8. uint8_t  WAV_DataBuffer[2][WAV_BUFFER_SIZE];
  9. uint8_t  WAV_NextIndex = 0;
  10. uint8_t  WAV_PlayEnded = 0;
  11. uint8_t  WAV_PlayState = 0;


  12. /* Private variables ---------------------------------------------------------*/
  13. uint32_t WAV_Offset   = 0;
  14. uint32_t WAV_DataSize = 0;
  15. uint32_t WAV_TxLength = 0;


  16. /* Private function prototypes -----------------------------------------------*/
  17. /* Private functions ---------------------------------------------------------*/


  18. /* Exported variables --------------------------------------------------------*/
  19. /* Exported function prototypes ----------------------------------------------*/


  20. /*******************************************************************************
  21. * @brief      
  22. * @param      
  23. * @retval      
  24. * @attention   
  25. *******************************************************************************/
  26. void I2S_MultiTimerCallback(MultiTimer *timer, void *userData)
  27. {
  28.     WAV_PlaySong();

  29.     MultiTimerStart(&I2S_MultiTimer, 5000, I2S_MultiTimerCallback, "I2S");
  30. }


  31. /*******************************************************************************
  32. * @brief      
  33. * @param      
  34. * @retval      
  35. * @attention   
  36. *******************************************************************************/
  37. void mI2S_Init(void)
  38. {
  39.     GPIO_InitTypeDef GPIO_InitStructure;
  40.     I2S_InitTypeDef  I2S_InitStructure;

  41.     RCC_APB2PeriphClockCmd(RCC_APB2ENR_SPI1, ENABLE);

  42.     I2S_InitStructure.I2S_Mode       = I2S_Mode_MasterTx;
  43.     I2S_InitStructure.I2S_Standard   = I2S_Standard_Phillips;
  44.     I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
  45.     I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
  46.     I2S_InitStructure.I2S_AudioFreq  = I2S_AudioFreq_44k;
  47.     I2S_InitStructure.I2S_CPOL       = I2S_CPOL_Low;
  48.     I2S_Init(SPI1, &I2S_InitStructure);

  49.     SPI_DMACmd(SPI1, ENABLE);

  50.     I2S_Cmd(SPI1, ENABLE);

  51.     SPI1->GCTL |= (SPI_GCR_SPIEN | SPI_GCR_MODE | SPI_GCR_TXEN);

  52.     RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOC, ENABLE);

  53.     GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_6);
  54.     GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_6);
  55.     GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_6);
  56.     GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_6);

  57.     GPIO_StructInit(&GPIO_InitStructure);
  58.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_4 | GPIO_Pin_5 |
  59.                                     GPIO_Pin_6 | GPIO_Pin_7;
  60.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  61.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
  62.     GPIO_Init(GPIOC, &GPIO_InitStructure);

  63.     GPIO_StructInit(&GPIO_InitStructure);
  64.     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;
  65.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  66.     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
  67.     GPIO_Init(GPIOC, &GPIO_InitStructure);

  68.     GPIO_WriteBit(GPIOC, GPIO_Pin_2, Bit_RESET);

  69.     MultiTimerStart(&I2S_MultiTimer, 5000, I2S_MultiTimerCallback, "I2S");
  70. }


  71. /*******************************************************************************
  72. * @brief      
  73. * @param      
  74. * @retval      
  75. * @attention   
  76. *******************************************************************************/
  77. void I2S_DMA_Transfer(uint16_t *Buffer, uint32_t BufferSize)
  78. {
  79.     DMA_InitTypeDef  DMA_InitStructure;
  80.     NVIC_InitTypeDef NVIC_InitStructure;

  81.     DMA_DeInit(DMA1_Channel1);

  82.     RCC_AHBPeriphClockCmd(RCC_AHBENR_DMA1, ENABLE);

  83.     DMA_StructInit(&DMA_InitStructure);
  84.     DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->TXREG);
  85.     DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32_t)Buffer;
  86.     DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralDST;
  87.     DMA_InitStructure.DMA_BufferSize         = BufferSize;
  88.     DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
  89.     DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;
  90.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
  91.     DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;
  92.     DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;
  93.     DMA_InitStructure.DMA_Priority           = DMA_Priority_High;
  94.     DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;
  95.     DMA_InitStructure.DMA_Auto_reload        = DMA_Auto_Reload_Disable;
  96.     DMA_Init(DMA1_Channel1, &DMA_InitStructure);

  97.     if(DMA_InitStructure.DMA_PeripheralBaseAddr == ((uint32_t)(&(SPI1->TXREG))))
  98.     {
  99.         DMA_SetChannelMuxSource(DMA1_Channel1, DMA1_MUX_SPI1_TX);

  100.         if(DMA_GetChannelMuxSource(DMA1_Channel1) != DMA1_MUX_SPI1_TX)
  101.         {
  102.             while(1);
  103.         }
  104.     }

  105.     NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
  106.     NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
  107.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  108.     NVIC_Init(&NVIC_InitStructure);

  109.     DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
  110.     DMA_ITConfig(DMA1_Channel1, DMA_IT_HT, ENABLE);

  111.     DMA_Cmd(DMA1_Channel1, ENABLE);
  112. }


  113. /*******************************************************************************
  114. * @brief      
  115. * @param      
  116. * @retval      
  117. * @attention   
  118. *******************************************************************************/
  119. uint8_t WAV_DecodeFile(WAV_TypeDef *pWav, uint32_t Address)
  120. {
  121.     ChunkRIFF_TypeDef *WAV_RIFF;
  122.     ChunkFMT_TypeDef  *WAV_FMT ;
  123.     ChunkFACT_TypeDef *WAV_FACT;
  124.     ChunkDATA_TypeDef *WAV_DATA;

  125.     uint8_t WAV_HeadBuffer[512];


  126.     SPI_FLASH_FastRead(Address, WAV_HeadBuffer, 512);


  127.     /* 获取RIFF块 */
  128.     WAV_RIFF = (ChunkRIFF_TypeDef *)WAV_HeadBuffer;

  129.     /* 是WAV格式文件 */
  130.     if(WAV_RIFF->Format == 0x45564157)
  131.     {
  132.         /* 获取FMT块 */
  133.         WAV_FMT  = (ChunkFMT_TypeDef *)(WAV_HeadBuffer+12);

  134.         /* 读取FACT块 */
  135.         WAV_FACT = (ChunkFACT_TypeDef *)(WAV_HeadBuffer+12+8+WAV_FMT->ChunkSize);

  136.         if((WAV_FACT->ChunkID == 0x74636166) || (WAV_FACT->ChunkID == 0x5453494C))
  137.         {
  138.             /* 具有FACT/LIST块的时候(未测试) */
  139.             pWav->DataStart=12+8+WAV_FMT->ChunkSize+8+WAV_FACT->ChunkSize;
  140.         }
  141.         else
  142.         {
  143.             pWav->DataStart=12+8+WAV_FMT->ChunkSize;
  144.         }

  145.         /* 读取DATA块 */
  146.         WAV_DATA = (ChunkDATA_TypeDef *)(WAV_HeadBuffer+pWav->DataStart);

  147.         /* 解析成功 */
  148.         if(WAV_DATA->ChunkID == 0x61746164)
  149.         {
  150.             pWav->AudioFormat   = WAV_FMT->AudioFormat;     /* 音频格式 */
  151.             pWav->nChannels     = WAV_FMT->NumOfChannels;   /* 通道数 */
  152.             pWav->SampleRate    = WAV_FMT->SampleRate;      /* 采样率 */
  153.             pWav->BitRate       = WAV_FMT->ByteRate*8;      /* 得到位速 */
  154.             pWav->BlockAlign    = WAV_FMT->BlockAlign;      /* 块对齐 */
  155.             pWav->BitsPerSample = WAV_FMT->BitsPerSample;   /* 位数,16/24/32位 */

  156.             pWav->DataSize      = WAV_DATA->ChunkSize;      /* 数据块大小 */
  157.             pWav->DataStart     = pWav->DataStart+8;        /* 数据流开始的地方 */

  158.             printf("\r\npWav->AudioFormat   : %d", pWav->AudioFormat);
  159.             printf("\r\npWav->nChannels     : %d", pWav->nChannels);
  160.             printf("\r\npWav->SampleRate    : %d", pWav->SampleRate);
  161.             printf("\r\npWav->BitRate       : %d", pWav->BitRate);
  162.             printf("\r\npWav->BlockAlign    : %d", pWav->BlockAlign);
  163.             printf("\r\npWav->BitsPerSample : %d", pWav->BitsPerSample);
  164.             printf("\r\npWav->DataSize      : %d", pWav->DataSize);
  165.             printf("\r\npWav->DataStart     : %d", pWav->DataStart);

  166.             WAV_Offset   = pWav->DataStart + Address;
  167.             WAV_DataSize = pWav->DataSize;
  168.         }
  169.     }

  170.     return 0;
  171. }


  172. /*******************************************************************************
  173. * @brief      
  174. * @param      
  175. * @retval      
  176. * @attention   
  177. *******************************************************************************/
  178. void WAV_PrepareData(void)
  179. {
  180.     if(WAV_NextIndex == 0)
  181.     {
  182.         SPI_FLASH_FastRead(WAV_Offset + WAV_TxLength, WAV_DataBuffer[0], WAV_BUFFER_SIZE);
  183.     }
  184.     else
  185.     {
  186.         SPI_FLASH_FastRead(WAV_Offset + WAV_TxLength, WAV_DataBuffer[1], WAV_BUFFER_SIZE);
  187.     }

  188.     WAV_TxLength += WAV_BUFFER_SIZE;

  189.     if(WAV_TxLength > WAV_DataSize) WAV_PlayEnded = 1;
  190. }


  191. /*******************************************************************************
  192. * @brief      
  193. * @param      
  194. * @retval      
  195. * @attention   
  196. *******************************************************************************/
  197. void WAV_PlayHandler(void)
  198. {
  199.     if(WAV_PlayEnded == 0)
  200.     {
  201.         I2S_DMA_Transfer((uint16_t *)&WAV_DataBuffer[WAV_NextIndex][0], (WAV_BUFFER_SIZE / 2));
  202.     }
  203.     else
  204.     {
  205.         DMA_Cmd(DMA1_Channel1,    DISABLE);

  206.         printf("\r\nWAV Play Finish!\r\n");     WAV_PlayState = 0;
  207.     }

  208.     if(WAV_NextIndex == 0) WAV_NextIndex = 1;
  209.     else                   WAV_NextIndex = 0;
  210. }


  211. /*******************************************************************************
  212. * @brief      
  213. * @param      
  214. * @retval      
  215. * @attention   
  216. *******************************************************************************/
  217. void WAV_PlaySong(void)
  218. {
  219.     WAV_TypeDef WaveFile;

  220.     if(WAV_PlayState == 0)
  221.     {
  222.         if(WAV_DecodeFile(&WaveFile, 0x00000000) == 0)
  223.         {
  224.             if((WaveFile.BitsPerSample == 16) && (WaveFile.nChannels == 2) &&
  225.                (WaveFile.SampleRate  > 44000) && (WaveFile.SampleRate < 48100))
  226.             {
  227.                 WAV_NextIndex = 0;
  228.                 WAV_PlayEnded = 0;
  229.                 WAV_TxLength  = 0;
  230.                 WAV_PlayState = 1;

  231.                 printf("\r\n");
  232.                 printf("\r\nWAV Data Size : %d, Data Start : 0x%08x", WAV_DataSize, WAV_Offset);
  233.                 printf("\r\n");

  234.                 WAV_PrepareData();
  235.                 WAV_PlayHandler();
  236.             }
  237.             else
  238.             {
  239.                 printf("\r\nWAV File Format Error!\r\n"); return;
  240.             }
  241.         }
  242.         else
  243.         {
  244.             printf("\r\nNo WAV File!\r\n"); return;
  245.         }
  246.     }
  247.     else
  248.     {
  249.         printf("\r\nThe Song Is Not Over Yet!\r\n");
  250.     }
  251. }


  252. /*******************************************************************************
  253. * @brief      
  254. * @param      
  255. * @retval      
  256. * @attention   
  257. *******************************************************************************/
  258. void DMA1_Channel1_IRQHandler(void)
  259. {
  260.     if(DMA_GetITStatus(DMA1_IT_TC1) != RESET)
  261.     {
  262.         DMA_ClearITPendingBit(DMA1_IT_TC1);

  263.         WAV_PlayHandler();
  264.     }

  265.     if(DMA_GetITStatus(DMA1_IT_HT1) != RESET)
  266.     {
  267.         DMA_ClearITPendingBit(DMA1_IT_HT1);

  268.         WAV_PrepareData();
  269.     }
  270. }


  271. #endif


还有其它等等功能,由于篇幅太长就不这边一一列举出来,大家可以下载最后的软件工程源代码进行学习和研究。


软件工程源代码
最后我们附上完整的软件工程源代码,供大家下载学习!!!
MindSDK版本: EVB-L0136_MindSDK_20220901.zip (571.89 KB, 下载次数: 36)
LibSample版本: EVB-L0136.zip (1.15 MB, 下载次数: 50)


打赏榜单

21小跑堂 打赏了 100.00 元 2022-11-08
理由:恭喜通过原创审核!期待您更多的原创作品

评论

大佬就是大佬呀,敢为人先,不走寻常路,以一人之力在不依靠官方例程的情况下玩转整个开发板,有实力,有耐心,值得肯定!文章的描写在完善点会得到更高的打赏哦~  发表于 2022-11-8 13:28
 楼主| xld0932 发表于 2022-11-2 16:11 | 显示全部楼层
通过官方网站,下载到了MM32L0130的数据手册、用户手册、芯片支持包、EVB-L0130开发板用户手册、原理图,以及MindSKD驱动和示例程序;

但对于EVB-L0130开发板,并没有提供对应的软件代码,本文作者通过学习MM32L0130系列MCU的各个模块,再结合EVB-L0130开发带有功能,给大家分享了基于EVB-L0130开发板的软件工程,并提供了详细的源码!

 楼主| xld0932 发表于 2022-11-4 10:41 | 显示全部楼层
20块开发板免费送~灵动MM32L0136C7P等你来申请!
https://bbs.21ic.com/icview-3262804-1-1.html?fromuser=xld0932
(出处: 21ic电子技术开**坛)

感觉给这个活动打了个好样呢
chenjun89 发表于 2022-11-5 12:56 来自手机 | 显示全部楼层
还有音箱,那必须得加个WIFI模块啊。
 楼主| xld0932 发表于 2022-11-6 00:17 | 显示全部楼层
chenjun89 发表于 2022-11-5 12:56
还有音箱,那必须得加个WIFI模块啊。

所有的功能都是基于EVB-L0136开发板的板载资源实现的,还没有扩展外接的模块哦
duo点 发表于 2022-11-8 16:33 | 显示全部楼层
没有WIFI模块的音响是不完美的,最好再搞个蓝牙模块
NOo02 发表于 2022-11-8 18:26 | 显示全部楼层
博主能否出一篇使用YModem或者XMODEM传输协议到SPI FLASH的读写操作的文章,一直对这个协议传输到Flash没搞明白
 楼主| xld0932 发表于 2022-11-8 22:12 | 显示全部楼层
NOo02 发表于 2022-11-8 18:26
博主能否出一篇使用YModem或者XMODEM传输协议到SPI FLASH的读写操作的文章,一直对这个协议传输到Flash没搞 ...

你看我之前发的帖子呢,有专门讲YMODEM、XMODEM协议传输的分享
昨天 发表于 2022-11-11 15:38 | 显示全部楼层
这是给大家提前出考试的答案吗?……
tpgf 发表于 2022-12-1 17:36 | 显示全部楼层
这个开发板是不是带了一个小小的显示屏啊 请问是什么接口呢
 楼主| xld0932 发表于 2022-12-2 09:10 | 显示全部楼层
tpgf 发表于 2022-12-1 17:36
这个开发板是不是带了一个小小的显示屏啊 请问是什么接口呢

段码液晶显示屏,L0136带有一个SLCD,可以驱动段码屏显示……帖中准备相关资料中,已经附上了段码屏的手册了哈……
qcliu 发表于 2022-12-2 13:09 | 显示全部楼层
代码风格不错 不过要是能多加点解释就更好了
drer 发表于 2022-12-2 13:18 | 显示全部楼层
chenjun89 发表于 2022-11-5 12:56
还有音箱,那必须得加个WIFI模块啊。

请问为什么加上音箱的话就需要外扩wifi模块呢
coshi 发表于 2022-12-2 13:29 | 显示全部楼层
音频输出效果如何呀  噪音会不会比较大呢
kxsi 发表于 2022-12-2 14:33 | 显示全部楼层
请问芯片支持包里边含有一些代码工程吗
 楼主| xld0932 发表于 2022-12-2 15:42 | 显示全部楼层
kxsi 发表于 2022-12-2 14:33
请问芯片支持包里边含有一些代码工程吗

你说的是Keil Pack的话,没有……这个KEIL PACK看原厂是怎么封装的了……你说的是LibSample或者是MindSDK的话,不仅有示例程序,也有底层驱动……
wiba 发表于 2022-12-3 08:19 | 显示全部楼层
xld0932 发表于 2022-12-2 15:42
你说的是Keil Pack的话,没有……这个KEIL PACK看原厂是怎么封装的了……你说的是LibSample或者是MindSDK ...

请问一下  您说的这两个都需要用户自主进行下载吗
 楼主| xld0932 发表于 2022-12-5 09:12 | 显示全部楼层
wiba 发表于 2022-12-3 08:19
请问一下  您说的这两个都需要用户自主进行下载吗

是的
xu@xupt 发表于 2022-12-8 23:40 | 显示全部楼层
学习啦
春娇霹雳娃 发表于 2022-12-9 17:29 | 显示全部楼层
学习啦
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:King.Xu

77

主题

3023

帖子

38

粉丝
快速回复 在线客服 返回列表 返回顶部
个人签名:King.Xu

77

主题

3023

帖子

38

粉丝
快速回复 在线客服 返回列表 返回顶部