本帖最后由 jinglixixi_457498010 于 2021-9-24 16:02 编辑

K32W061以ARM®Cortex®-M4 为内核,主频为48MHz,内含640KBEmbedded Flash,152KB SRAM ,128KB ROM 2. 1 x NOR Flash 1MB、1 x FT230XS、2 x 13pinArduino Interface 3. 2 x I2Cs、2 x SPI、2 x UARTs、10bit x PWM、1 x DMIC、1 x QSPI 、22 x GPIOs、1 x 12bit ADC、1 x 10bit DAC、1 × IR Module、1 × RNG等。
限于篇幅的原因,这里仅介绍功能相对独立的PWM、RTC、A/D及UART的使用。
1.PWM
利用PWM的占空比调节作用可以通过LED的亮度,但比较不便的是该输出口处于PIO3上,为此,要观察调节过程只能外观一个LED指示模块。
该PWM调节的主程序为:
  1. int main(void)
  2. {
  3. pwm_config_t pwmConfig;
  4. uint32_t pwmSourceClockFreq;
  5. uint32_t pwmChannelClockFreq;
  6. SYSCON->CODESECURITYPROT = 0x87654320;
  7. BOARD_BootClockRUN();
  8. BOARD_InitDebugConsole();
  9. BOARD_InitPins();
  10. /* Get default configuration */
  11. PWM_GetDefaultConfig(&pwmConfig);
  12. /* PWM Init with default clock selected */
  13. PWM_Init(EXAMPLE_PWM, &pwmConfig);
  14. /* Get the default source clock frequency */
  15. pwmSourceClockFreq = CLOCK_GetFreq(kCLOCK_Pwm);
  16. /* Set up PWM channel to generate PWM pulse of 10ms with a starting 100% duty cycle */
  17. pwmChan.pol_ctrl      = kPWM_SetHighOnMatchLowOnPeriod;
  18. pwmChan.dis_out_level = kPWM_SetLow;
  19. pwmChan.prescaler_val = 0;
  20. pwmChannelClockFreq   = pwmSourceClockFreq / (1 + pwmChan.prescaler_val);
  21. pwmChan.period_val    = USEC_TO_COUNT(10000, pwmChannelClockFreq);
  22. /* Compare value starts same as period value to give a 100% starting duty cycle */
  23. pwmChan.comp_val = pwmChan.period_val;
  24. PWM_SetupPwm(EXAMPLE_PWM, kPWM_Pwm3, (pwm_setup_t *)&pwmChan);
  25. /* Clear interrupt status for PWM channel */
  26. PWM_ClearStatusFlags(EXAMPLE_PWM, kPWM_Pwm3);
  27. /* Enable IRQ in NVIC for PWM channel 3 */
  28. EnableIRQ(PWM3_IRQn);
  29. /* Enable PWM channel interrupt */
  30. PWM_EnableInterrupts(EXAMPLE_PWM, kPWM_Pwm3);
  31. /* Start the PWM generation channel */
  32. PWM_StartTimer(EXAMPLE_PWM, kPWM_Pwm3);
  33. while (1)
  34. {
  35. __WFI();
  36. }
  37. }
主程序是通过中断来周期性的修改占空比以产生调节效果,其变化梯度为1/2000,其中断程序如下:
  1. voidPWM3_IRQHandler(void)
  2. {
  3. staticuint32_t count = 2000;
  4. count--;
  5. if (count == 0)
  6. {
  7. count = 2000;
  8. }
  9. /* Change the compare value in the channel setup structure to change the duty cycle, ramping up over 2000 steps */
  10. pwmChan.comp_val = (count * pwmChan.period_val) / 2000;
  11. /* Re-apply the channel setup to update the compare value */
  12. PWM_SetupPwm(EXAMPLE_PWM, kPWM_Pwm3, (pwm_setup_t *)&pwmChan);
  13. /* Handle PWM channel interrupt, clear interrupt status */
  14. PWM_ClearStatusFlags(EXAMPLE_PWM, kPWM_Pwm3);
  15. }
经编译和下载,其执行效果如图1所示。
1.jpg
1b.jpg
图1运行效果
动画演示1:
pwm.gif

2.RTC电子时钟
在K32W061片内,配有RTC计时器,通过与OLED屏配合即可轻松实现一个电子时钟。
由于前面已提供了OLED屏的驱动方法及程序,因此通过下面的程序即可了解RTC的使用方法。
电子时钟的程序为:
  1. int main(void)
  2. {
  3. uint32_t sec;
  4. uint32_t currSeconds;
  5. uint8_t index,t,d;
  6. rtc_datetime_t date;
  7. /* Board pin, clock, debug console init */
  8. /* Security code to allow debug access */
  9. gpio_pin_config_t led_config = {kGPIO_DigitalOutput,1,};
  10. SYSCON->CODESECURITYPROT = 0x87654320;
  11. /* Init the boards */
  12. BOARD_BootClockRUN();
  13. BOARD_InitDebugConsole();
  14. BOARD_InitPins();
  15. /* RTC clocks dividers */
  16. CLOCK_SetClkDiv(kCLOCK_DivRtcClk, 32, false);
  17. CLOCK_SetClkDiv(kCLOCK_DivRtc1HzClk, 1, false);
  18. CLOCK_uDelay(10000);
  19. /* Init output LED GPIO. */
  20. GPIO_PortInit(GPIO, BOARD_LED_PORT);
  21. GPIO_PinInit(GPIO, BOARD_LED_PORT, 11, &led_config);
  22. GPIO_PinInit(GPIO, BOARD_LED_PORT, 10, &led_config);
  23. OLED_Init();
  24. OLED_Clear();
  25. OLED_ShowChar(16,0,'-',16);
  26. OLED_ShowChar(40,0,'-',16);
  27. OLED_ShowChar(16,2,':',16);
  28. OLED_ShowChar(40,2,':',16);
  29. /* Init RTC */
  30. RTC_Init(RTC);
  31. /* Set a start date time and start RT */
  32. date.year   = 2021U;
  33. date.month  = 9U;
  34. date.day    = 15U;
  35. date.hour   = 9U;
  36. date.minute = 30;
  37. date.second = 0;
  38. /* RTC time counter has to be stopped before setting the date & time in the TSR register */
  39. RTC_StopTimer(RTC);
  40. /* Set RTC time to default */
  41. RTC_SetDatetime(RTC, &date);
  42. /* Start the RTC time counter */
  43. RTC_StartTimer(RTC);
  44. RTC_GetDatetime(RTC, &date);
  45. OLED_ShowNum(0,0,date.year,2,16);
  46. OLED_ShowNum(24,0,date.month,2,16);
  47. OLED_ShowNum(48,0,date.day,2,16);
  48. t=date.second;
  49. d=date.day;
  50. while (1)
  51. {
  52. RTC_GetDatetime(RTC, &date);
  53. if(t!=date.second)
  54. {
  55. if(t!=date.second)
  56. {
  57. OLED_ShowNum(0,0,date.year,2,16);
  58. OLED_ShowNum(24,0,date.month,2,16);
  59. OLED_ShowNum(48,0,date.day,2,16);
  60. }
  61. OLED_ShowNum(0,2,date.hour,2,16);
  62. OLED_ShowNum(24,2,date.minute,2,16);
  63. OLED_ShowNum(48,2,date.second,2,16);
  64. t=date.second;
  65. }
  66. }
  67. }
该程序的处理流程为:先进行初始化,然后设置系统的起始时间并启动RTC,最终通过循环体内显示处理来输出RTC计时值。值得注意的是,为了防止过度的更新处理,是在出现秒变化时才进行时间的更新,而日期的更新则是在日期变化时。
经编译和下载,其执行效果如图2所示。
2.jpg
图2运行效果
动画演示2:(文件大小受限,无法上传)

3.A/D
使用A/D 的数模转换功能可以采集外部的模拟信号,在配合OLED屏显示的情况下,可直观地观察到检测结果。
下面是由A0口获取模拟信号的检测主程序:
  1. intmain(void)
  2. {
  3. /* Initialize board hardware. */
  4. /* Security code to allow debug access */
  5. /* Board pin, clock, debug console init */
  6. /* Security code to allow debug access */
  7. gpio_pin_config_t led_config = {kGPIO_DigitalOutput,1,};
  8. SYSCON->CODESECURITYPROT = 0x87654320;
  9. /* reset FLEXCOMM for USART */
  10. RESET_PeripheralReset(kFC0_RST_SHIFT_RSTn);
  11. /* Init the boards */
  12. BOARD_BootClockRUN();
  13. BOARD_InitDebugConsole();
  14. BOARD_InitPins();
  15. /* Enable the power and clock for ADC. */
  16. ADC_ClockPower_Configuration();
  17. PRINTF("ADC basic example.\r\n");
  18. #if !(defined(FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC) &&    FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC)
  19. #ifdefined(FSL_FEATURE_ADC_HAS_CALIB_REG) && FSL_FEATURE_ADC_HAS_CALIB_REG
  20. /* Calibration after power up. */
  21. if (ADC_DoSelfCalibration(DEMO_ADC_BASE))
  22. #else
  23. uint32_t frequency;
  24. #ifdefined(SYSCON_ADCCLKDIV_DIV_MASK)
  25. frequency = CLOCK_GetFreq(DEMO_ADC_CLOCK_SOURCE) /    CLOCK_GetClkDivider(kCLOCK_DivAdcClk);
  26. #else
  27. frequency = CLOCK_GetFreq(DEMO_ADC_CLOCK_SOURCE);
  28. #endif/* SYSCON_ADCCLKDIV_DIV_MASK */
  29. /* Calibration after power up. */
  30. if (ADC_DoSelfCalibration(DEMO_ADC_BASE, frequency))
  31. #endif/* FSL_FEATURE_ADC_HAS_CALIB_REG */
  32. {
  33. PRINTF("ADC_DoSelfCalibration() Done.\r\n");
  34. }
  35. else
  36. {
  37. PRINTF("ADC_DoSelfCalibration() Failed.\r\n");
  38. }
  39. #endif/* FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC */
  40. /* Configure the converter and work mode. */
  41. ADC_Configuration();
  42. PRINTF("Configuration Done.\r\n");
  43. #ifdefined(FSL_FEATURE_ADC_HAS_CTRL_RESOL) & FSL_FEATURE_ADC_HAS_CTRL_RESOL
  44. PRINTF("ADC Full Range: %d\r\n", g_Adc_12bitFullRange);
  45. #endif/* FSL_FEATURE_ADC_HAS_CTRL_RESOL */
  46. GPIO_PortInit(GPIO, BOARD_LED_PORT);
  47. GPIO_PinInit(GPIO, BOARD_LED_PORT, 11, &led_config);
  48. GPIO_PinInit(GPIO, BOARD_LED_PORT, 10, &led_config);
  49. OLED_Init();
  50. OLED_Clear();
  51. OLED_ShowString(0,0,"K32W061 TEST",16);
  52. if (SysTick_Config(SystemCoreClock / 1000U))
  53. {
  54. while (1)
  55. {
  56. }
  57. }
  58. SysTick_DelayTicks(1000U);
  59. OLED_ShowString(0,2,"adc=",16);
  60. while (1)
  61. {
  62. ADC_DoSoftwareTriggerConvSeqA(DEMO_ADC_BASE);
  63. /* Wait for the converter to be done. */
  64. while (!ADC_GetChannelConversionResult(DEMO_ADC_BASE,   DEMO_ADC_SAMPLE_CHANNEL_NUMBER, &adcResultInfoStruct))
  65. {
  66. }
  67. OLED_ShowNum(32,2,adcResultInfoStruct.result,4,16);
  68. SysTick_DelayTicks(1000U);
  69. }
  70. }
由于在数据采集过程中,需要一定的转换时间,且数据采集也是有时间间隔要求的,故需要在程序中添加一个延时函数,以控制采样间隔。
经编译和下载,其执行效果如图3所示,通过电位器的调节可改变模拟信号的输入值。
3.jpg
3b.jpg
图3运行效果
动画演示3:(文件大小受限,无法上传)
4.UART
程序通讯是一种常用的功能,尤其是在未配置其它外设的情况下,串口几乎是唯一的观察工具。此外,设备间的数据共享也是靠串行通讯来完成的。
这里我们是使用串口来控制MP3模块的播放,该模块的实物如图4所示,图5是引脚的用途。
4.jpg
图4 模块外观
5.jpg
图5 引脚用途
在实际的使用中,我们只需连接电源引脚、扬声器引脚及串口的接收引脚。
控制MP3播放的主程序如下:
  1. #include"board.h"
  2. #include"fsl_usart.h"
  3. #include"pin_mux.h"
  4. #include<stdbool.h>
  5. #define DEMO_USART USART0
  6. #define DEMO_USART_CLK_SRC kCLOCK_Fro32M
  7. #define DEMO_USART_CLK_FREQ CLOCK_GetFreq(DEMO_USART_CLK_SRC)
  8. uint8_t cmd3[10] = {0X7E, 0xFF, 0x06, 0X03, 0x00, 0x00, 0x01, 0xFE, 0xF7, 0XEF};
  9. uint8_t rxbuff[20] = {0};
  10. intmain(void)
  11. {
  12. uint8_t ch;
  13. usart_config_t config;
  14. /* Security code to allow debug access */
  15. SYSCON->CODESECURITYPROT = 0x87654320;
  16. /* attach clock for USART(debug console) */
  17. CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
  18. /* reset FLEXCOMM for USART */
  19. RESET_PeripheralReset(kFC0_RST_SHIFT_RSTn);
  20. BOARD_BootClockRUN();
  21. BOARD_InitDebugConsole();
  22. BOARD_InitPins();
  23. USART_GetDefaultConfig(&config);
  24. config.baudRate_Bps = 9600U;
  25. config.enableTx     = true;
  26. config.enableRx     = true;
  27. USART_Init(DEMO_USART, &config, DEMO_USART_CLK_FREQ);
  28. USART_WriteBlocking(DEMO_USART, txbuff, sizeof(txbuff) - 1);
  29. while (1)
  30. {
  31. USART_ReadBlocking(DEMO_USART, &ch, 1);
  32. USART_WriteBlocking(DEMO_USART, &ch, 1);
  33. }
  34. }
由于MP3模块的通讯速率为9600bps,故将串行通讯的波特率设为9600。
6.jpg
图6 播放控制