STM32使用中断和DAM完成串口通信

(一)串口协议和RS-232标准

1.串口协议介绍

串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单、便捷,因此大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常使用该通 讯方式输出调试信息。
在计算机科学里,大部分复杂的问题都可以通过分层来简化。如芯片被分为内核层和片上外设;STM32
标准库则是在寄存器与用户代码之间的软件层。对于通讯协议,我们也以分层的方式来理解,最基本的是把它分为物理层和协议层。

2.RS-232 标准

RS-232是现在主流的串行通信接口之一。由于RS232接口标准出现较早,难免有不足之处,主要有以下四点:
(1)接口的信号电平值较高,易损坏接口电路的芯片。RS232接口任何一条信号线的电压均为负逻辑关系。即:逻辑“1”为-3— -15V;逻辑“0”:+3— +15V ,噪声容限为2V。即要求接收器能识别高于+3V的信号作为逻辑“0”,低于-3V的信号作为逻辑“1”,TTL电平为5V为逻辑正,0为逻辑负 。与TTL电平不兼容故需使用电平转换电路方能与TTL电路连接。
(2)传输速率较低,在异步传输时,比特率为20Kbps;因此在51CPLD开发板中,综合程序波特率只能采用19200,也是这个原因。
(3)接口使用一根信号线和一根信号返回线与地线构成共地的传输形式,这种共地传输容易产生共模干扰,所以抗噪声干扰性弱。
(4)传输距离有限,最大传输距离标准值为50英尺,实际上也只能用在15米左右。

3.TTL电平

TTL器件输出低电平要小于0.8V,高电平要大于2.4V。输入,低于1.2V就认为是0,高于2.0就认为是1。于是TTL电平的输入低电平的噪声容限就只有(0.8-0)/2=0.4V,高电平的噪声容限为(5-2.4)/2=1.3V。

4.RS-232与TTL电平的区别

1.电平的上限和下限定义不一样,CMOS具有更大的抗噪区域。 同是5伏供电的话,ttl一般是1.7V和3.5V的样子,CMOS一般是2.2V,2.9V的样子,不准确,仅供参考。

2.电流驱动能力不一样,ttl一般提供25毫安的驱动能力,而CMOS一般在10毫安左右。

3.需要的电流输入大小也不一样,一般ttl需要2.5毫安左右,CMOS几乎不需要电流输入。

4.很多器件都是兼容TTL和CMOS的,datasheet会有说明。如果不考虑速度和性能,一般器件可以互换。但是需要注意有时候负载效应可能引起电路工作不正常,因为有些ttl电路需要下一级的输入阻抗作为负载才能正常工作。

5.USB/TTL转232模块介绍

"USB/TTL转232"模块是一种常见的串口转换器,用于将USB接口转换为TTL电平的串口(RS-232)信号。其工作原理如下:
1.USB接口:"USB/TTL转232"模块的一侧是USB接口,用于与计算机或其他USB主机设备进行连接。
2.USB转UART芯片:内部集成了一个USB转UART(通用异步收发传输)芯片,该芯片负责实现USB与串口之间的数据转换。常见的芯片型号包括CH340、FT232RL等。
3.UART引脚:UART芯片的引脚包括接收线(RX)、发送线(TX)和地线(GND)。这些引脚用于与目标设备(如微控制器、单片机等)进行连接。
4.TTL电平转换:UART芯片将USB接口传输的数据转换为TTL电平的串口信号。在TTL电平中,逻辑高通常为3.3V或5V,逻辑低则为0V。这种电平转换使得"USB/TTL转232"模块可以与使用串口通信的设备进行连接。
5.RS-232电平转换(可选):某些"USB/TTL转232"模块还配备了RS-232电平转换电路,以便直接与RS-232设备进行连接。这种电平转换会将TTL电平的信号转换为RS-232电平,其中逻辑高通常为-3V至-15V,逻辑低为+3V至+15V。

(二)使用中断完成串口通信(输出"hello window!")

打开STM32CubeMX,选择创建一个新项目,选择STM32F103C8T6
在这里插入图片描述
设置SYS
在这里插入图片描述
设置RCC

设置USART1
在这里插入图片描述
设置NVIC
在这里插入图片描述
创建项目
在这里插入图片描述
在这里插入图片描述
打开keil5,打开刚刚创建的项目
在这里插入图片描述
打开main.c,将其中代码改成下列代码

#include "main.h"
#include "usart.h"
#include "gpio.h"
#include <string.h>

void SystemClock_Config(void);

char c;//指令 0:停止  1:开始
char message[]="hello Windows\n";//输出信息
char tips[]="CommandError\n";//提示1
char tips1[]="start.....\n";//提示2
char tips2[]="stop......\n";//提示3
int flag=0;//标志 0:停止发送 1.开始发送


int main(void)
{
	HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
	HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);
  while (1)
  {
		if(flag==1){
			HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message),0xFFFF); 
			HAL_Delay(1000);
		}
  }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(c=='0'){
		flag=0;
		HAL_UART_Transmit(&huart1, (uint8_t *)&tips2, strlen(tips2),0xFFFF); 
	}
	

	else if(c=='1'){
		flag=1;
		HAL_UART_Transmit(&huart1, (uint8_t *)&tips1, strlen(tips1),0xFFFF); 
	}
	

	else {
		flag=0;
		HAL_UART_Transmit(&huart1, (uint8_t *)&tips, strlen(tips),0xFFFF); 
	}

		HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);  
}

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};


  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)
{
  __disable_irq();
  while (1)
  {
  }
}

打开烧录软件
在这里插入图片描述
打开串口助手,可以看到成功的结果
在这里插入图片描述

(三)使用DAM完成串口通信

1.DAM介绍

DMA,全称Direct Memory Access,即直接存储器访问。DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。
DMA用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。
DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节。
我们知道,数据传输,首先需要的是数据的源地址、数据传输位置的目标地址、传递数据多少的数据传输量、进行多少次传输的传输模式。DMA所需要的核心参数,便是这四个。
每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过软件来配置。

2.使用STM32CubeMX

创建一个新项目,选择STM32F103C8T6,开始设置RCC
在这里插入图片描述
设置USART1
在这里插入图片描述
在这里插入图片描述
添加两个通道
在这里插入图片描述
创建项目
在这里插入图片描述
打开keil,将main.c的主函数改成下列代码

int main(void)
{

  HAL_Init();

	uint8_t message[] = "Hello Window\n";  

  SystemClock_Config();

  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();

  while (1)
  {
    HAL_UART_Transmit_DMA(&huart1, (uint8_t *)message, sizeof(message));
	  HAL_Delay(1000);
  }
}

运行查看结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STM32F103中,实现串口通讯可以通过中断方式进行。下面是实现串口通讯的步骤: 1. 配置串口:首先需要配置串口的参数,包括波特率、数据位、停止位、校验位等。可以使用STM32提供的库函数进行配置。 2. 使能串口中断:通过设置相应的寄存器,使能串口接收和发送中断。 3. 编写中断服务函数:编写串口接收和发送的中断服务函数。当接收到数据或者发送完成时,中断服务函数会被触发。 4. 中断优先级设置:设置串口中断的优先级,确保中断服务函数按照预期的顺序执行。 5. 启动串口:使能串口的接收和发送功能。 下面是一个示例代码,演示了如何使用中断实现串口通讯: ```c #include "stm32f10x.h" void USART1_IRQHandler(void) { if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { // 接收到数据 uint8_t data = USART_ReceiveData(USART1); // 处理接收到的数据 // ... } if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET) { // 发送完成 // 可以继续发送下一个字节 // ... } } int main(void) { // 配置串口参数 USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); // 使能串口中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_ITConfig(USART1, USART_IT_TXE, ENABLE); // 设置串口中断优先级 NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // 启动串口 USART_Cmd(USART1, ENABLE); while (1) { // 主循环 // ... } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值