串口协议和RS-232标准:
串口协议:
串口通信是一种通过串行数据传输的方式进行的通信。它使用一对引脚(发送线TX和接收线RX)进行单向或双向的数据传输。
常见的串口协议包括UART(通用异步收发传输)和USART(通用同步异步收发传输),它们定义了数据传输的格式、速率、起始位、停止位等参数。
RS-232标准:
RS-232(Recommended Standard 232)是一种广泛用于串行通信的标准,定义了连接设备之间串行通信时的电气特性、信号极性、机械接口等。
RS-232标准规定了常见的串口参数,如波特率、数据位、停止位和奇偶校验等。
RS232电平与TTL电平的区别:
RS232电平通常采用负逻辑,即高电平表示逻辑0,低电平表示逻辑1。而TTL电平通常是正逻辑,高电平表示逻辑1,低电平表示逻辑0。
RS232电平的电压范围更大,一般为-15V至+15V,而TTL电平的电压范围通常在0V至5V。
RS232标准使用的连接器通常是DB-9或DB-25,而TTL通常使用的是0.1英寸间距的引脚。
"USB/TTL转232"模块(以CH340芯片模块为例)的工作原理:
CH340芯片:
CH340是一款USB转串口的芯片,常用于制作USB转TTL(UART)的模块,例如USB/TTL转232模块。
它提供了USB与串口之间的桥接功能,使得计算机可以通过USB接口与串口设备进行通信。
工作原理:
当连接USB/TTL转232模块到计算机的USB端口时,CH340芯片会被激活。
CH340通过USB接口与计算机通信,驱动程序将其识别为一个虚拟串口设备。
用户通过计算机的串口终端或软件向虚拟串口发送数据,CH340芯片将数据转换为串口信号并通过TTL电平输出到模块的TX引脚。
接收方向上,CH340芯片接收TTL电平的串口信号,将其转换为USB可识别的信号,通过USB接口发送到计算机。
这种模块的优势在于方便连接串口设备到计算机,而不需要计算机具备物理串口。它常用于与嵌入式系统、单片机等设备进行调试和通信。用户可以通过USB/TTL转232模块在计算机上模拟一个串口,使得与串口设备的通信变得更加简便。
DMA简介
DMA,即直接内存访问(Direct Memory Access),是一种计算机系统中的数据传输技术,旨在提高数据传输的效率和性能。DMA允许外设(如硬盘驱动器、网络适配器、图形卡等)直接访问系统内存,而不需要通过中央处理器(CPU)的干预,从而减轻CPU的负担。
以下是DMA的主要特点和工作原理:
特点和优势:
提高性能: DMA允许外设与内存之间的数据传输在不干扰CPU正常运行的情况下进行。这可以大大提高数据传输速度和整体系统性能。
减少CPU开销: 在传统的CPU控制数据传输中,CPU需要不断地介入数据传输过程,处理每个数据包。DMA可以减轻CPU的负担,使其能够专注于其他重要任务。
支持大数据传输: DMA适用于需要大规模数据传输的应用,如音频/视频处理、网络通信等。
降低延迟: DMA可以显著降低数据传输的延迟,因为数据可以直接从外设到内存,或者反之,而无需等待CPU的干预。
工作原理:
DMA的工作原理通常包括以下步骤:
初始化DMA控制器: CPU首先初始化DMA控制器,配置数据传输的源地址、目标地址、传输长度等参数。
DMA请求: 当外设需要进行数据传输时,它会发送一个DMA请求信号给DMA控制器,指示需要启动数据传输。
DMA控制器操作: DMA控制器接收到DMA请求后,会启动数据传输,并控制数据的流向,将数据从源地址传输到目标地址。这一过程完全独立于CPU。
数据传输完成: DMA控制器在数据传输完成后,会发送一个中断信号给CPU,以便CPU知道数据传输已经完成。
CPU处理中断: CPU在接收到DMA完成的中断信号后,可以进行相关的处理,例如更新数据结构或继续执行其他任务。
总之,DMA是一项关键的系统性能优化技术,特别是在需要高速数据传输的应用中,如多媒体处理、高速网络通信和大规模数据存储中,它能够显著提高系统的效率和性能。
创建新工程
选择芯片
配置RCC,开启外部高速时钟
配置USART1,选择异步通信
添加两个通信信道
然后生成keil代码即可
最终代码如下:
#include "main.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"
void SystemClock_Config(void);
uint8_t flag=1;
uint8_t rx_buf[6];//接收串口数据存放的数组
int strEqual(char rcData[6],char rcData2[6])
{
for(uint8_t i = 0 ; i < 6 ; i++){
if (rcData[i] != rcData2[i]) return 0;
}
return 1;
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//当输入的指令为“stop!"时,发送提示并改变flag=0
if(strEqual(rx_buf,"stop!"))
{
flag=0;
}
//当输入的指令为"start"时,发送提示并改变flag=1
else if(strEqual(rx_buf,"start"))
{
flag=1;
}
HAL_UART_Receive_DMA(&huart1,(uint8_t*)rx_buf,5);
}
int main(void)
{
HAL_Init();
uint8_t message[] = "hello windows!\n"; //定义数据发送数组
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
HAL_UART_Receive_DMA(&huart1,(uint8_t*)rx_buf,5);//设置DMA接收到的数据存放在rx_buf中
while (1)
{
if(flag==1)
{
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)message, sizeof(message));
HAL_Delay(600);
}
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#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,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
实验效果
用Keil的软件仿真逻辑分析仪功能观察串口输出波形
可以参考前文
总结
基于中断(Interrupt)和DMA(Direct Memory Access)方式的串口通信是计算机系统中常见的数据传输方式。这两种方式在串口通信中的应用有着不同的特点和优势:
基于中断的串口通信:
工作原理: 在中断方式下,当串口接收到数据时,会触发一个中断信号,中断控制器会中断CPU的正常执行,CPU会跳转到特定的中断处理程序中,处理接收到的数据。
优势:
实时性强: 中断可以实现实时响应,及时处理接收到的数据,适用于对实时性要求较高的应用。
灵活性: 中断可以根据需要动态配置,可以处理不同优先级的中断请求,提供了较好的灵活性。
缺点:
CPU开销较高: 中断需要不断地中断CPU的正常执行,处理中断请求,可能会引起较大的CPU开销。
延迟相对较高: 由于需要中断CPU的执行,中断方式的串口通信可能引入较高的延迟。
基于DMA的串口通信:
工作原理: 在DMA方式下,当串口接收到数据时,DMA控制器会直接将数据传输到内存中的指定位置,无需CPU的干预,从而减轻了CPU的负担。
优势:
降低CPU开销: DMA方式可以显著降低CPU的开销,使CPU能够专注于其他任务,提高系统的整体性能。
减小延迟: 由于数据直接传输到内存,DMA方式可以降低数据传输的延迟,提高响应速度。
适用于大数据传输: DMA适用于需要大规模数据传输的情况,能够高效地传输大量数据。
缺点:
配置复杂: DMA的配置可能相对较复杂,需要确保DMA控制器的正确配置,以及避免DMA冲突等问题。
综上所述,基于中断的串口通信适用于对实时性要求较高,且数据量不大的场景,而基于DMA的串口通信适用于大数据传输、降低CPU开销和提高响应速度的场景。选择合适的方式取决于应用的具体需求和系统性能要求。