完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
硬件原理图:主芯片
引脚封装图: 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两种低功耗工作模式。 复位电路 滤波电路 内部稳压 调试下载 默认使用SWD接口下载程序,原理图如下: 板载指示灯 用于查看系统运行状态,原理图如下: 软件功能工程创建 具体如何创建工程就不所说明了,官方例程都有说明,我主要说下的我的目录结构设计: 串口通讯 内部集成 2 个通用异步收发器 (UART),支持异步全双工、同步半双工和单线半双工模式,支持硬件数据流控和多机通信,还支持 LIN(局域互连网络);可编程数据帧结构,可以通过小数波特率发生器提供宽范围的波特率选择。内置定时器模块,支持等待超时检测、接收空闲检测、自动波特率检测和通用定时功能。UART 控制器工作在双时钟域下,允许在深度休眠模式下进行数据的接收,接收完成中断可以唤醒 MCU 回到运行模式。注意:仅 UART1 支持 LIN 和定时器功能;UART2 可通过片内外设互联与 BtiM/GTIM/ATIM 的从模式协同工作实现超时定时器相关功能。我们接着实现串口通讯功能; 1.串口功能硬件引脚 使用串口2来是实现通讯,再看引脚的复用功能。 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 %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ 3.编写打印测试函数 static void Printf_Function(void) { DEBUG_LOG("\r\n"); DEBUG_LOG(" Compile time:"); DEBUG_LOG(__DATE__); DEBUG_LOG(" "); DEBUG_LOG(__TIME__); DEBUG_LOG("\r\n+-------------------+\r\n"); DEBUG_LOG("%s,%s,%d,%s\r\n", __FUNCTION__,__FILE__,__LINE__,__DATE__); DEBUG_LOG("\r\n+-------------------+\r\n"); } 4.查看串口终端信息 使用MobaXterm终端工具查看: 5.注意点 为了让代码支持GNU扩展,keil设置需要注意: 同时,串口打印的时候,添加头文件"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 #include #include #include #define GLOB_LOG_EVEL LOG_DEBUG typedef enum { FALSE, TRUE } status; // 定义日志级别 typedef enum { LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR } LogLevel; //extern LogMsg lmsg; // 颜色 #define Blue "\033[34m" // Blue #define Green "\033[32m" // Green #define Yellow "\033[33m" // Yellow #define Red "\033[31m" // Red #define Reset "\033[0m" // Reset color // 记录日志的宏定义 #define LOG_MESSAGE(format, ...) printf("[NTP]:%s(),Line:%05d: " format "\r\n", __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 "\r\n", message); break; case LOG_INFO: printf(Green "INFO: %s" Reset "\r\n", message); break; case LOG_WARNING: printf(Yellow "WARNING: %s" Reset "\r\n", message); break; case LOG_ERROR: printf(Red "ERROR: %s" Reset "\r\n", message); break; default: printf("UNKNOWN: %s\n", 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.终端输出 串口中断 CW32单片机的串口有好几种工作方式,异步全双工,同步半双工,单线半双工,由于没有DMA通道,为了避免频繁的进入中断,采用串口接收中断,串口查询发送方式实现收发; 配置简单队列消息,实现方式如下: 1、定义队列结构 #define myQ2_SIZE 512 #define RxBuffer2_SIZE myQ2_SIZE typedef 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、查看串口终端收发 从截图可以看出,当前收发数据一致; |
|
相关推荐
|
|
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-27 20:36 , Processed in 0.412919 second(s), Total 39, Slave 29 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号