0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

CW32L010学习笔记

捨得 来源:捨得 作者:捨得 2024-11-15 17:40 次阅读

​CW32学习开发笔记

硬件原理图:

芯片

image-20241114103849101

引脚封装图:

image-20241114104051352

** CW32L010 是基于 eFlash 的单芯片低功耗微控制器,集成了主频高达 48MHz 的 ARM® Cortex®-M0+ 内核、**
高速嵌入式存储器(多至 64K 字节 FLASH 和多至 4K 字节 SRAM)以及一系列全面的增强型外设和 I/O 口。
所有型号都提供全套的通信接口(二路 UART、一路 SPI 和一路 I2C)、12 位高速 ADC、四组通用和基本定时器
一组低功耗定时器以及一组高级控制 PWM 定时器。

供电电源

** 使用type-c直接供电即可,不需要再接其他电源转换芯片,CW32L010 可以在 -40℃到 85℃的温度范围内工作,供电电压宽达 1.62V ~ 5.5V。支持 Sleep 和 DeepSleep两种低功耗工作模式。**

image-20241114104435067

复位电路

滤波电路

image-20241114104852343

内部稳压

image-20241114105052457

image-20241114105024829

调试下载

默认使用SWD接口下载程序,原理图如下:

image-20241114105146199

板载指示灯

用于查看系统运行状态,原理图如下:

image-20241114110648242

软件功能

工程创建

具体如何创建工程就不所说明了,官方例程都有说明,我主要说下的我的目录结构设计:

image-20241114105830013

串口通讯

** 内部集成 2 个通用异步收发器 (UART),支持异步全双工、同步半双工和单线半双工模式,支持硬件数据流控**
和多机通信,还支持 LIN(局域互连网络);可编程数据帧结构,可以通过小数波特率发生器提供宽范围的
波特率选择。内置定时器模块,支持等待超时检测、接收空闲检测、自动波特率检测和通用定时功能。
UART 控制器工作在双时钟域下,允许在深度休眠模式下进行数据的接收,接收完成中断可以唤醒 MCU 回到
运行模式。注意:仅 UART1 支持 LIN 和定时器功能;UART2 可通过片内外设互联与 BTIM/GTIM/ATIM 的从模式协同工
作实现超时定时器相关功能。我们接着实现串口通讯功能;

  • 1.串口功能硬件引脚

image-20241114135526600

使用串口2来是实现通讯,再看引脚的复用功能。

image-20241114135659092

  • 2.代码实现
#include  "bsp_uart2.h"
 #include "cw32l010_gpio.h"
 #include "cw32l010_uart.h"
 #include  "stdio.h"
 #include "cw32l010_sysctrl.h"//UARTx
 #define  DEBUG_UARTx                   CW_UART2
 #define  DEBUG_UART_CLK                SYSCTRL_APB1_PERIPH_UART2
 #define  DEBUG_UART_APBClkENx          SYSCTRL_APBPeriphClk_Enable1
 #define  DEBUG_UART_BaudRate           115200
 #define  DEBUG_UART_UclkFreq           HSIOSC_VALUE     //串口全速运行 //UARTx GPIO
 #define  DEBUG_UART_GPIO_CLK           (SYSCTRL_AHB_PERIPH_GPIOB)
 #define  DEBUG_UART_TX_GPIO_PORT       CW_GPIOB
 #define  DEBUG_UART_TX_GPIO_PIN        GPIO_PIN_5
 #define  DEBUG_UART_RX_GPIO_PORT       CW_GPIOB
 #define  DEBUG_UART_RX_GPIO_PIN        GPIO_PIN_6//GPIO AF
 #define  DEBUG_UART_AFTX               PB05_AFx_UART2TXD()
 #define  DEBUG_UART_AFRX               PB06_AFx_UART2RXD()
 ​
 ​
 static void UART_Configuration(void)
 {
 //    //外设时钟使能,放在外设里面自己进行使能
     
     DEBUG_UART_APBClkENx(DEBUG_UART_CLK, ENABLE);
 
 
 UART_InitTypeDef UART_InitStructure = {0};
 ​
     UART_InitStructure.UART_BaudRate = DEBUG_UART_BaudRate;
     UART_InitStructure.UART_Over = UART_Over_16;
     UART_InitStructure.UART_Source = UART_Source_PCLK;
     UART_InitStructure.UART_UclkFreq = DEBUG_UART_UclkFreq;
     UART_InitStructure.UART_StartBit = UART_StartBit_FE;
     UART_InitStructure.UART_StopBits = UART_StopBits_1;
     UART_InitStructure.UART_Parity = UART_Parity_No ;
     UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
     UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx;
     UART_Init(DEBUG_UARTx, &UART_InitStructure);
 ​
 }
 ​
 ​
 /**
  * @brief 配置GPIO
  *
  */
 static void GPIO_Configuration(void)
 {
     GPIO_InitTypeDef GPIO_InitStructure = {0};
 
 //外设时钟使能,放在外设里面自己进行使能
 SYSCTRL_AHBPeriphClk_Enable(DEBUG_UART_GPIO_CLK, ENABLE);
     
     GPIO_WritePin(DEBUG_UART_TX_GPIO_PORT, DEBUG_UART_TX_GPIO_PIN,GPIO_Pin_SET);    // 设置TXD的默认电平为高,空闲
 ​
     GPIO_InitStructure.Pins = DEBUG_UART_TX_GPIO_PIN;
     GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
     GPIO_Init(DEBUG_UART_TX_GPIO_PORT, &GPIO_InitStructure);
 ​
     GPIO_InitStructure.Pins = DEBUG_UART_RX_GPIO_PIN;
     GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
     GPIO_Init(DEBUG_UART_RX_GPIO_PORT, &GPIO_InitStructure);
 ​
      //UART TX RX 复用
     DEBUG_UART_AFTX;
     DEBUG_UART_AFRX;
 }
 ​
 ​
 ​
 void UART2_Configuration(void)
 {
 UART_Configuration();
 GPIO_Configuration();
 }
 ​
 ​
 #ifdef __GNUC__
     /* With GCC/RAISONANCE, small printf (option LD Linker- >Libraries- >Small printf
     set to 'Yes') calls __io_putchar() */
     #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
 #else
     #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
 #endif /* __GNUC__ */
 ​
 ​
 /**
  * @brief Retargets the C library printf function to the UART.
  *
  */
 PUTCHAR_PROTOTYPE
 {
     UART_SendData_8bit(DEBUG_UARTx, (uint8_t)ch);
 ​
     while (UART_GetFlagStatus(DEBUG_UARTx, UART_FLAG_TXE) == RESET);
 ​
     return ch;
 }
 ​
 size_t __write(int handle, const unsigned char * buffer, size_t size)
 {
     size_t nChars = 0;
 ​
     if (buffer == 0)
     {
         /*
          * This means that we should flush internal buffers.  Since we
          * don't we just return.  (Remember, "handle" == -1 means that all
          * handles should be flushed.)
          */
         return 0;
     }
 ​
 ​
     for (/* Empty */; size != 0; --size)
     {
         UART_SendData_8bit(DEBUG_UARTx, *buffer++);
         while (UART_GetFlagStatus(DEBUG_UARTx, UART_FLAG_TXE) == RESET);
         ++nChars;
     }
 ​
     return nChars;
 }
 ​
 /******************************************************************************
  * EOF (not truncated)
  ******************************************************************************/
 #ifdef  USE_FULL_ASSERT
 /**
   * @brief  Reports the name of the source file and the source line number
   *         where the assert_param error has occurred.
   * @param  file: pointer to the source file name
   * @param  line: assert_param error line source number
   * @retval None
   */
 void assert_failed(uint8_t *file, uint32_t line)
 {
     /* USER CODE BEGIN 6 */
     /* User can add his own implementation to report the file name and line number,
        tex: printf("Wrong parameters value: file %s on line %drn", file, line) */
     /* USER CODE END 6 */
 }
 #endif /* USE_FULL_ASSERT */
  • 3.编写打印测试函数
static void Printf_Function(void)
 {
     DEBUG_LOG("rn");
     DEBUG_LOG("  Compile time:");
     DEBUG_LOG(__DATE__);
     DEBUG_LOG("  ");
     DEBUG_LOG(__TIME__);
     DEBUG_LOG("rn+-------------------+rn");
     DEBUG_LOG("%s,%s,%d,%srn", __FUNCTION__,__FILE__,__LINE__,__DATE__);
     DEBUG_LOG("rn+-------------------+rn");
 }
  • 4.查看串口终端信息
    使用MobaXterm终端工具查看:

image-20241114140550582

  • 5.注意点

为了让代码支持GNU扩展,keil设置需要注意:

image-20241114140950288

同时,串口打印的时候,添加头文件"stdio.h";

GPIO口输入输出

根据板载资源,使用板载的LED来测试。前面硬件说明的时候提到,使用的引脚为PB00;就直接上代码了。

  • 1.编写驱动代码
#include  "drv_led.h"
 ​
 ​
 ​
 ​
 // 初始化 LED 引脚
 void LED_Init(void) 
 {
     GPIO_InitTypeDef GPIO_InitStruct = {0};
 ​
     __SYSCTRL_GPIOB_CLK_ENABLE();  
 ​
     GPIO_InitStruct.IT = GPIO_IT_NONE;
     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
     GPIO_InitStruct.Pins = LED_GPIO_PINS;
 ​
     GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct);
 
 }
 ​
 // 控制 LED 开关
 void LED_Control(GPIO_PinState state) 
 {
 GPIO_WritePin(LED_GPIO_PORT, LED_GPIO_PINS,state);
 }
 ​
 // 切换 LED 状态
 void LED_Toggle(void) {
     GPIO_TogglePin(LED_GPIO_PORT, LED_GPIO_PINS);
 }
 ​
 // 读取 LED 状态
 int LED_Read(void) {
     return GPIO_ReadPin(LED_GPIO_PORT, LED_GPIO_PINS) == GPIO_Pin_SET ? 1 : 0;
 }
 ​
 // 定义并初始化 LED 操作结构体实例
 LED_Ops_t myLED = {
     .init = LED_Init,
     .control = LED_Control,
     .toggle = LED_Toggle,
     .read = LED_Read
 };
 ​
  • 2.编写测试程序
int32_t main(void)
 {
 
 bsp_init();
 driver_init();
 ​
     while(1)
     {
 SysTickDelay(1000);
 myLED.toggle();
     }
 }

调试下载之后,可直接观察板载LED灯是否在循环闪烁。

调试等级

  • 1.直接上代码,调试等级头文件;
#ifndef __LOG_H
 #define __LOG_H
 #include < stdio.h >
 #include < stdlib.h >
 #include < string.h >
 #include < stdarg.h >
 #define GLOB_LOG_EVEL           LOG_DEBUGtypedef enum {
     FALSE,
     TRUE
     } status;
 // 定义日志级别
 typedef enum {
     LOG_DEBUG,
     LOG_INFO,
     LOG_WARNING,
     LOG_ERROR
     } LogLevel;
 ​
 ​
 ​
 //extern LogMsg lmsg;
 // 颜色
 #define Blue    "�33[34m" // Blue
 #define Green   "�33[32m" // Green
 #define Yellow  "�33[33m" // Yellow
 #define Red     "�33[31m" // Red
 #define Reset   "�33[0m"  // Reset color
 ​
 ​
 // 记录日志的宏定义#define LOG_MESSAGE(format, ...) printf("[NTP]:%s(),Line:%05d: " format "rn", __FUNCTION__, __LINE__, ##__VA_ARGS__)void LOG_MSG(LogLevel level, const char *message);
 #endif
  • 2.功能函数实现文件:
#include "log.h"// 日志输出函数
 void LOG_MSG(LogLevel level, const char *message) {
     switch (level) {
         case LOG_DEBUG:
             printf(Blue "DEBUG: %s" Reset "rn", message);
             break;
         case LOG_INFO:
             printf(Green "INFO: %s" Reset "rn", message);
             break;
         case LOG_WARNING:
             printf(Yellow "WARNING: %s" Reset "rn", message);
             break;
         case LOG_ERROR:
             printf(Red "ERROR: %s" Reset "rn", message);
             break;
         default:
             printf("UNKNOWN: %sn", message);
             break;
     }
 }
  • 3.编写测试函数
/*宏定义错误码信息*/
 static void Error_Code_Info(void)
 { 
 DEBUG_LOG("%d", SYSTEM_OK);
 DEBUG_LOG("%d", SYSTEM_ERR_E_1);
 DEBUG_LOG("%d", SYSTEM_ERR_E_2);
 DEBUG_LOG("%d", SYSTEM_ERR_MQTT_INFO_ERROR);
 ​
 ​
 LOG_MSG(LOG_DEBUG, "This is a debug message");
 LOG_MSG(LOG_INFO, "This is an info message");
 LOG_MSG(LOG_WARNING, "This is a warning message");
 LOG_MSG(LOG_ERROR, "This is an error message");
 }
  • 4.终端输出

image-20241114145804066

串口中断

CW32单片机的串口有好几种工作方式,异步全双工,同步半双工,单线半双工,由于没有DMA通道,为了避免频繁的进入中断,采用串口接收中断,串口查询发送方式实现收发;

配置简单队列消息,实现方式如下:

  • 1、定义队列结构
#define myQ2_SIZE     512
 #define RxBuffer2_SIZE   myQ2_SIZEtypedef volatile struct
 {
     uint8_t     m_getIdx;
     uint8_t     m_putIdx;
     uint8_t     m_entry[ myQ2_SIZE ];
 } myQ2;
 ​
 extern  myQ2   volatile RxBuffer2;
 extern  myQ2   volatile TxBuffer2;
 ​
 void  UART2_Buffer_Init(void);
  • 2、初始化队列结构
myQ2   volatile RxBuffer2;
 myQ2   volatile TxBuffer2;
 ​
 ​
 void  UART2_Buffer_Init(void)
 {
     CBUF_Init(RxBuffer2);
     CBUF_Init(TxBuffer2);
 }
 ​
  • 3、使能串口接收中断
void NVIC_Configuration(void)
 {
     //优先级,无优先级分组
     NVIC_SetPriority(DEBUG_UART_IRQ, 0);
     //UARTx中断使能
     NVIC_EnableIRQ(DEBUG_UART_IRQ);
 
 
 //使能UARTx RC中断
     UART_ITConfig(DEBUG_UARTx, UART_IT_RC, ENABLE);
 UART_ClearITPendingBit(CW_UART2, UART_IT_RC);
 
 }
  • 4、编写测试函数,实现串口功能收发
int32_t main(void)
 {
 bsp_init();
 driver_init();
     while(1)
     {
 uint16_t  dataLen=0;
 dataLen = CBUF_Len(RxBuffer2);
 if(dataLen!=0)
 {
 //拷贝数据
 memcpy((char*)TxBuffer2.m_entry,(char*)RxBuffer2.m_entry,dataLen);
 //查询发送数据
 UART_SendBuf_Polling(CW_UART2,TxBuffer2.m_entry,dataLen);
 
 USART2_Clear();
 }
 SysTickDelay(1000);
 myLED.toggle();
     }
 }
  • 5、查看串口终端收发

image-20241115144847070

从截图可以看出,当前收发数据一致;

控制台Shell

下面介绍下开源项目是 letter-shell,一个功能强大的嵌入式shell,letter shell 3.x是一个C语言编写的,可以嵌入在程序中的嵌入式shell,通俗一点说就是一个串口命令行,可以通过命令行调用、运行程序中的函数。目前 letter-shell 3.0版本支持的功能有:

  • 命令自动补全
  • 快捷键功能定义
  • 命令权限管理
  • 用户管理
  • 变量支持

项目地址: [https://github.com/NevermindZZT/letter-shell]

移植过程:

  • 1.复制源码到工程中:

image-20241115165344228

  • 2.在自定义接口shell_port.c中实现自己的串口读写函数
#include "shell.h"
 #include "main.h"
 #include "bsp_uart2.h"
 #include "shell_port.h"
 ​
 Shell shell;
 char shellBuffer[512];
 ​
 ​
 /**
  * @brief 用户shell写
  * 
  * @param data 数据
  * @param len 数据长度
  * 
  * @return short 实际写入的数据长度
  */
 short userShellWrite(char *data, unsigned short len)
 {
 UART_SendBuf_Polling(CW_UART2,(uint8_t *)data, len);
     return len;
 }
 ​
 ​
 /**
  * @brief 用户shell读
  * 
  * @param data 数据
  * @param len 数据长度
  * 
  * @return short 实际读取到
  */
 short userShellRead(char *data, unsigned short len)
 {
 return UART2_GetString((uint8_t *)data, len);
 }
 ​
 /**
  * @brief 用户shell上锁
  * 
  * @param shell shell
  * 
  * @return int 0
  */
 int userShellLock(Shell *shell)
 {
 return 0;
 }
 ​
 /**
  * @brief 用户shell解锁
  * 
  * @param shell shell
  * 
  * @return int 0
  */
 int userShellUnlock(Shell *shell)
 {
 return 0;
 }
 ​
 /**
  * @brief 用户shell初始化
  * 
  */
 void userShellInit(void)
 {
 ​
 //注册自己实现的写函数
     shell.write = userShellWrite;
 //shell.read = userShellRead;
 //调用shell初始化函数
     shellInit(&shell, shellBuffer, 512);
 
 }
  • 3.在终端函数中定义

对于裸机环境,在主循环中调用shellTask,或者在接收到数据时,调用shellHandler,我这里在中断中调用

void UART2_IRQHandler(void)
 {
     /* USER CODE BEGIN */
     uint8_t TxRxBuffer;
     if (UART_GetITStatus(CW_UART2, UART_IT_RC) != RESET)
     {
 /*使用简易队列进行接收数据*/
 TxRxBuffer = UART_ReceiveData_8bit(CW_UART2);
 shellHandler(&shell,TxRxBuffer);
         CBUF_Push(RxBuffer2, TxRxBuffer);
         UART_ClearITPendingBit(CW_UART2, UART_IT_RC);
     }
     /* USER CODE END */
 }
  • 4.调用初始化shell
userShellInit();
  • 5.串口终端实现结果

image-20241115170003058

查看当前系统时钟:

image-20241115170036353

其他实现方式,参考官方文档说明。

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 芯片
    +关注

    关注

    453

    文章

    50297

    浏览量

    421283
  • CW32
    +关注

    关注

    1

    文章

    182

    浏览量

    552
收藏 人收藏

    评论

    相关推荐

    基于CW32L083的线控器方案设计

    基于武汉芯源推出的CW32L083设计的空调线控器产品.
    的头像 发表于 06-25 14:23 5w次阅读
    基于<b class='flag-5'>CW32L</b>083的线控器方案设计

    CW32L083 RTC初始化设置

    介绍CW32L083的RTC初始化设置
    的头像 发表于 06-24 10:16 1459次阅读
    <b class='flag-5'>CW32L</b>083 RTC初始化设置

    CW32L083智能温湿度监控系统

    基于CW32L芯片制作的无线温温度采集系统
    的头像 发表于 07-07 07:59 1193次阅读
    <b class='flag-5'>CW32L</b>083智能温湿度监控系统

    基于CW32L010单片机的低成本电动工具方案

    本方案采用武汉芯源的CW32L010F8P6作为主控实现低成本电动工具方案,通过PWM方波控制算法进行电机转速控制,内部高精度AD转换实现电机电压、反电动势、电流等信号的采样,并实时进行故障停机保护等功能。
    的头像 发表于 10-30 16:04 794次阅读
    基于<b class='flag-5'>CW32L010</b>单片机的低成本电动工具方案

    CW32L010安全低功耗MCU,树立M0+产品行业新标杆!

    2024年9月26日,武汉芯源半导体CW32L010系列产品正式官方发布。这款产品以其卓越的产品性能,迅速在业界引起了广泛关注,并成功树立M0+产品行业的新标杆。 CW32L010系列产品
    发表于 10-09 10:08

    【产品介绍】32位低功耗MCU CW32L031系列产品介绍

    适用于便携医疗产品,如血氧计、血糖仪、额温枪等。武汉芯源官方网站已经发布了CW32L031系列MCU的数据手册、用户手册、应用笔记等技术文档,以及配套的StartKit开发板资料、底层外设驱动软件库
    发表于 09-16 10:30

    【应用笔记】CS32L010 IAP 升级

    本技术文档旨在帮助客户实现IAP 升级提供一个参考方案和模板。本文档提供基于 UART 升级的 MCU 参考代码和 PC 端的升级工具软件。*附件:CS32L010 IAP 升级.pdf
    发表于 10-09 16:44

    【应用笔记】CS32L010 设计注意事项

    本技术文档描述了CS32L010 在 电路设计,Flash操作 和 AWK 唤醒低功耗睡眠模式 方面需要注意的事项。 参考本文档提供的注意事项,有助于提高电路的稳定性和可靠性,也有助于 MCU 软件
    发表于 11-22 16:42

    NRF24L01_学习笔记

    NRF24L01_学习笔记
    发表于 03-04 18:25 12次下载

    ES32F010x应用笔记

    电子发烧友网站提供《ES32F010x应用笔记.pdf》资料免费下载
    发表于 09-22 14:43 0次下载
    ES32F<b class='flag-5'>010</b>x应用<b class='flag-5'>笔记</b>

    STK682-010-E 应用笔记

    STK682-010-E 应用笔记
    发表于 11-14 21:08 5次下载
    STK682-<b class='flag-5'>010</b>-E 应用<b class='flag-5'>笔记</b>

    武汉芯源CW32L083开发板介绍

    CW32L083VxTxStartKit评估板为用户提供一种经济且灵活的方式使用CW32L083VxTx芯片构建系统原型,可进行性能、功耗、功能等各方面快速验证
    的头像 发表于 10-20 11:41 829次阅读
    武汉芯源<b class='flag-5'>CW32L</b>083开发板介绍

    CW32L010安全低功耗MCU,树立M0+产品行业新标杆!

    2024年9月26日,武汉芯源半导体CW32L010系列产品正式官方发布。这款产品以其卓越的产品性能,迅速在业界引起了广泛关注,并成功树立M0+产品行业的新标杆。CW32L010系列产品
    的头像 发表于 10-09 10:12 409次阅读
    <b class='flag-5'>CW32L010</b>安全低功耗MCU,树立M0+产品行业新标杆!

    CW32L0100核心板的使用体验

    最近我们迎来了CW32L010新品的正式发布,标志着嵌入式技术领域的又一次创新突破。今日,我们有幸进行该新品的首次使用体验,以一块L010核心板为例,体验一下这颗芯片。
    的头像 发表于 10-30 15:29 160次阅读
    <b class='flag-5'>CW32L</b>0100核心板的使用体验

    CW32L010 新品初体验

    最近我们迎来了CW32L010新品的正式发布,标志着嵌入式技术领域的又一次创新突破。今日,我们有幸进行该新品的首次使用体验,以一块L010核心板为例,体验一下这颗芯片。 一、核心板概览 如图所示
    的头像 发表于 11-14 17:45 79次阅读
    <b class='flag-5'>CW32L010</b> 新品初体验