大家好,最近做了一个小模块,是一个以太网转串口的DTU模块,说实话,现在DTU确实十分的常见,尤其是在工控或者是一些不宜修改的产品职中。所谓DTU是什么呢?
DTU 是 "Data Terminal Unit" 的缩写,中文通常翻译为“数据终端单元”。它是一种用于数据通信的设备,通常用于远程监控和数据采集系统中。DTU 的主要功能包括:
数据传输:将采集到的数据通过网络(如GPRS、3G、4G、以太网等)传输到远程服务器或监控中心。
数据处理:对采集到的数据进行预处理,如数据压缩、格式转换等。
远程控制:接收远程指令,控制现场设备的工作状态。
DTU 广泛应用于环境监测、电力监控、智能交通、工业自动化等领域。
本次比较幸运啊,获得了芯源的新品芯片“CW32L010”,该芯片主要是应用于低功耗方面,同时具有很好的优势,比如具有2个TTL串口,并且支持在低功耗模式下可以唤醒MCU,同时还有SPI,I2C,定时器等等外设,可谓是体积虽小,功能俱全。其实将其设计成一款低功耗的DTU来说,应该是一个不错的选择,而且这样来看可以让DTU变成独立电池供电的便携式设备了。
实际上的DTU基本上就是利用TTL实现的数据转换,之前做的小模块是利用APM32+沁恒的CH9120来实现的DTU,那么本次将APM32替换成CW32L010,利用其两个独立串口的先天优势,来实现DTU的基本功能。由于当时设计的CH9120是产品,所以不宜在此展示,但是逻辑是基本相同的,都是利用2个串口实现数据的交互。好,咱们说干就干~
图1 CW32L010StartKit开发板 从图1来看,板载设计还是比较丰富的,有存储,USB转串口,MCU,两个按键和一个复位按键,还有LED小灯等等,我觉得这作为MCU评估板来说,已经很是全面了。值得称赞的是通讯接口采用的是Type-c,这是非常不错的选择,现在数据线基本都是Type-c了,这样可以很好的找到数据线来使用。
接下来看数据手册,找到2个串口都在那里?
图2 CW32L010串口的选择 从图2来看,串口1可以使用PA05和PA06当做串口1,采用板载原生的PB05和PB06来作为串口2,目的是串口1收到的数据转换到串口2上,串口2收到的数据转换到串口1上,这就是一个DTU的基本通讯原理,如果有定制来说可以通过中断收到的数据进行处理,来实现个性化。
接下来就是编写代码了,找到官方的例程,本次使用的是串口带中断接收的例程,然后进行“魔改”,增加自己需要的串口1的一些初始化,并且加入中断函数,这样一个基本的DTU的程序部分就成型了代码如下:
串口1的基本定义:
//UART1
#define USER_UART1 CW_UART1
#define USER_UART1_CLK SYSCTRL_APB1_PERIPH_UART1
#define USER_UART1_APBClkENx SYSCTRL_APBPeriphClk_Enable1
#define USER_UART1_BaudRate 115200
#define USER_UART1_UclkFreq 8000000
//UARTx GPIO
#define USER_UART1_GPIO_CLK (SYSCTRL_AHB_PERIPH_GPIOA)
#define USER_UART1_TX_GPIO_PORT CW_GPIOA
#define USER_UART1_TX_GPIO_PIN GPIO_PIN_6
#define USER_UART1_RX_GPIO_PORT CW_GPIOA
#define USER_UART1_RX_GPIO_PIN GPIO_PIN_5
//GPIO AF
#define USER_UART1_AFTX PA06_AFx_UART1TXD()
#define USER_UART1_AFRX PA05_AFx_UART1RXD()
//中断
#define USER_UART1_IRQ UART1_IRQn
int32_t main(void)
{
//配置RCC
RCC_Configuration();
//配置GPIO
GPIO_Configuration();
UART1_GPIO_Configuration();
//配置UART
UART_Configuration();
UART1_Configuration();
//配置NVIC
NVIC_Configuration();
//使能UARTx RC中断
UART_ITConfig(DEBUG_UARTx, UART_IT_RC, ENABLE);
UART_SendString(DEBUG_UARTx, "\r\nCW32L010 UART Interrupt\r\n");
printf("\r\nCW32L010 UART Interrupt Example\r\n");
UART_ClearITPendingBit(CW_UART2, UART_IT_RC);
//使能UART1 RC中断
UART_ITConfig(CW_UART1, UART_IT_RC, ENABLE);
UART_SendString(CW_UART1, "\r\nCW32L010 UART1 Interrupt\r\n");
UART_ClearITPendingBit(CW_UART1, UART_IT_RC);
while(1)
{
//中断收发
}
}
串口中断函数:
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] This funcation handles UART1
*/
void UART1_IRQHandler(void)
{
/* USER CODE BEGIN */
uint8_t TxRxBuffer;
if (UART_GetITStatus(CW_UART1, UART_IT_RC) != RESET)
{
TxRxBuffer = UART_ReceiveData_8bit(CW_UART1);
UART_SendData_8bit(CW_UART2, TxRxBuffer);
UART_ClearITPendingBit(CW_UART1, UART_IT_RC);
}
/* USER CODE END */
}
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] This funcation handles UART2
*/
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);
UART_SendData_8bit(CW_UART1, TxRxBuffer);
UART_ClearITPendingBit(CW_UART2, UART_IT_RC);
}
/* USER CODE END */
}
最后,来看看效果吧,最左侧黑色背景是代码逻辑,中间的串口调试助手软件是串口1的接收和发送区,最右侧是串口2的接收和发送区,串口1采用的波特率是115200,串口2采用的是9600,当我们用串口1发送数据的时候,可以在串口2的接收区看到数据内容。同理串口2的发送也可以显示在串口1的接收区中。
图3 CW32L010 数据交互 图4 CW32L010数据交互 总结:其实芯源的芯片还是比较容易上手的,这次调试基本没费多少力气就实现了预设内容,但是有一点不太理解,串口1可以是PA5和PA6也可以是PA0与PA1,那么如何映射都是随便的是么?在此期间,我用PA0和PA1的串口1发现不能正常通讯,不知道是什么原因。不过后来换到PA5和PA6的IO端口之后,发现可以正常使用了,这里要是有说明手册来具体说明就好了。最后,感谢21ic和芯源的给力活动,后续将继续优化代码,升级成低功耗版本的DTU,这样就离产品更进一步了
|