第8周实验----基于中断/DMA方式的串口通信
一.配置CUBEMX。
选择STM32F103C8T6点击START PROJECT.
点击RCC 将HSE设置为CRYSTAL/CERAMIC RESONATOR
点击SYS 将DEBUG 设置为SERIAL WIRE
点击进入USART1,将MODE 设置为ASYNCHRONOUS
进入NVIC 将USART1 GLOBAL INTERRUT 选上
点击进入PROJECT MANAGER 输入PROJECT NAME(不能是中文)
勾选GENERATE PERIPHERAI
然后点击GENERATE CODE生成MDK文件。
二,代码烧录
打开烧录出的文件夹
进入MDK-ARM.打开文件工程
将下段代码复制粘贴入main.c文件内。
`#include “main.h”
#include “usart.h”
#include “gpio.h”
#include <string.h>
void SystemClock_Config(void);
char c;
char message[]=“hello Windows\n”;
char tips[]=“CommandError\n”;
char tips1[]=“Start…\n”;
char tips2[]=“Stop…\n”;
int flag=0;
const char START[] = “START”;
const char STOP[] = “STOP”;
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)
{
static uint8_t idx = 0; // 添加静态变量用于索引
char receivedChar = c;
if (receivedChar == START[idx]) {
idx++;
if (idx == strlen(START)) {
flag = 1; // 接收到START,设置flag为1
idx = 0; // 重置索引
}
} else if (receivedChar == STOP[idx]) {
idx++;
if (idx == strlen(STOP)) {
flag = 0; // 接收到STOP,设置flag为0
idx = 0; // 重置索引
}
} else if (idx > 0) {
// 如果接收字符不符合START或STOP的条件,且索引不为0,则重置索引
idx = 0;
}
if (flag == 1) {
HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message), 0xFFFF);
} else {
HAL_UART_Transmit(&huart1, (uint8_t *)&tips2, strlen(tips2), 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();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE`
然后点击保存编译,生成HEX文件,烧录进入单片机。
三.DMA通信:
创建新工程:
选择USTAR1
使能串口
创建工程
然后,将下列代码从粘贴到main.c中。
`#include “main.h”
#include “dma.h”
#include “usart.h”
#include “gpio.h”
void SystemClock_Config(void);
int stringcompare(char str1[6],char str2[6])
{
uint8_t i=0;
for(i = 0 ; i < 6 ; i++)
{
if (str1[i] != str2[i])
return 0;//如果输入数据与原有数据不符,返回0
}
return 1;//如果位数全部相同,则返回1
}
char start[6] = “start”;//初始字符串
uint8_t flag=3;//标志位
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,GPIO_PIN_SET);
//配置函数
uint8_t hello[20]=“Hello,Windows!\r\n”;
uint8_t stop[50]=“Stop!please enter ‘start’ to continue!\r\n”;
HAL_UART_Receive_DMA(&huart1,(uint8_t*)start,5);
while (1)
{
if(flag==1)//标志位为1,发送hellowindows
{
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,GPIO_PIN_SET);
HAL_UART_Transmit_DMA(&huart1,hello,20);
HAL_Delay(1000);
}
else if(flag==0)//标志位为0,停止发送0.
{
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,GPIO_PIN_RESET);
HAL_UART_Transmit_DMA(&huart1,stop,50);
flag=3;
}
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(stringcompare(start,"stop!"))//输入为stop时,标志位置0
{
flag=0;
}
else if(stringcompare(start,"start"))//输入为 start时,标志位置1
{
flag=1;
}
//重新设置中断
HAL_UART_Receive_DMA(&huart1,(uint8_t*)start,5);
}
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();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
- @brief This function is executed in case of error occurrence.
- @retval None
/
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 */` -
烧录进去
-
结果:
https://blog.csdn.net/vic_to_ry/article/details/110451036
https://blog.csdn.net/Constellation_zZ/article/details/134165845?spm=1001.2014.3001.5502
四:
了解串口协议和RS-232标准,以及RS232电平与TTL电平的区别
串口协议是用于数据通信的一种通信协议,它定义了数据的传输格式和数据交换的规则。串口通信常用于连接计算机与外部设备,例如串口打印机、调制解调器、传感器等。其中,RS-232 是一种常见的串口协议标准。
RS-232(Recommended Standard 232)是由美国电子工程师学会(Electronic Industries Association)制定的一套串行通信接口标准。它规定了数据的传输格式、电气特性以及接线方式等。
至于RS232电平和TTL电平,它们指的是串口通信中使用的电信号电平。RS232电平是一种标准的串口电平,通常使用±12V表示逻辑1和逻辑0。而TTL(Transistor-Transistor Logic)电平是另一种常见的电信号电平,通常使用0V表示逻辑0,以及3.3V或5V表示逻辑1。
区别主要有几点:
- 电压范围:RS232电平使用高低电平的正负电压表示逻辑1和逻辑0,而TTL电平使用固定的电压值表示逻辑1和逻辑0。
- 电气特性:RS232电平具有较高的电压和电流能力,可以实现较长距离的信号传输(通常可达15米以上),而TTL电平适用于较短距离的通信(通常在数米范围内)。
- 适用设备:由于电压范围和电气特性的不同,RS232电平主要用于连接计算机与外部设备,如调制解调器、打印机等,而TTL电平通常用于单片机与外部设备的通信。
需要注意的是,由于电压范围和电气特性的差异,直接连接RS232和TTL设备可能会导致电平不匹配和损坏设备。因此,如果需要连接RS232和TTL设备,可能需要使用电平转换器或专门的串口转换模块来进行信号转换。
了解"USB/TTL转232"模块(以CH340芯片模块为例)的工作原理
USB/TTL转232"模块(例如基于CH340芯片的模块)被广泛用于将USB接口的设备与RS-232串口设备进行连接。下面是其工作原理的一般过程:
- USB接口:该模块的一侧是USB接口,用于连接到计算机或其他USB主机设备。USB接口提供了数据传输和电源供应。
- CH340芯片:CH340是一款USB转串口芯片,模块上集成了该芯片。CH340芯片负责将USB中的数据转换为串行数据,以便与RS-232设备进行通信。
- TTL电平转换:在CH340芯片的输出端,存在TTL电平。TTL电平一般为0V表示逻辑0,以及3.3V或5V表示逻辑1。这种电平适用于与单片机或其他TTL电平设备进行通信。
- RS-232电平转换:通过RS-232电平转换电路,将TTL电平转换为RS-232电平。这是为了与RS-232设备进行兼容,RS-232电平一般是正负12V分别表示逻辑1和逻辑0。
- RS-232串口:模块的另一侧提供了RS-232串口,您可以通过它连接到其他RS-232设备,如调制解调器、打印机等。
SB主机设备。USB接口提供了数据传输和电源供应。
2. CH340芯片:CH340是一款USB转串口芯片,模块上集成了该芯片。CH340芯片负责将USB中的数据转换为串行数据,以便与RS-232设备进行通信。
3. TTL电平转换:在CH340芯片的输出端,存在TTL电平。TTL电平一般为0V表示逻辑0,以及3.3V或5V表示逻辑1。这种电平适用于与单片机或其他TTL电平设备进行通信。
4. RS-232电平转换:通过RS-232电平转换电路,将TTL电平转换为RS-232电平。这是为了与RS-232设备进行兼容,RS-232电平一般是正负12V分别表示逻辑1和逻辑0。
5. RS-232串口:模块的另一侧提供了RS-232串口,您可以通过它连接到其他RS-232设备,如调制解调器、打印机等。
总结来说,"USB/TTL转232"模块利用CH340芯片实现USB到串口的转换,并通过TTL到RS-232电平的转换,将USB接口转换为RS-232串口接口。