文章目录[隐藏]
前言
助力于快速使用串口功能,如果想了解串口协议等知识点等请自行搜索,
这里注明串口下功能实现常用的fputc、字符串发送函数、fgetc函数等函数写法。
实验了三个例子来展示printf函数、串口中断使用、串口基本使用。
一、使用cubemx进行串口基本配置
二、说明
一般配置好串口我们就可以实验使用串口向上位机发送内容了,即使用板子与PC端串口调试助手或者其他设备进行信息收发。
而进行信息发送一般使用HAL库自带的发送函数HAL_UART_Transmit
另一种方法便是调用C库中的printf打印函数,而该函数是依照fputc实现的,因此需要重写该函数才可以使用printf函数。而scanf函数是依靠fgetc完成的
下面常用函数详细说明这里不做赘述,喜欢自行查阅资料
重写fputc代码
int fputc(int ch,FILE * fp)
{
HAL_UART_Transmit(&huart1,(uint8_t * )&ch,1,0xffff);
return ch;
}
**重写fgetc实现程序可调用scanf及getchar等函数**
int fgetc(FILE *f)
{
int ch;
/* 等待串口输入数据 */
while (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) == RESET);
HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return (ch);
}
注意:使用时别忘记勾选微库选项,否则printf 不起作用
注意:使用时别忘记勾选微库选项,否则printf 不起作用
注意:使用时别忘记勾选微库选项,否则printf 不起作用
字符串发送函数
void Usart1_String(char *str)
{
int k=0;
do
{
HAL_UART_Transmit(&huart1,(uint8_t * )(str+k),1,0xffff);
k++;
}
while(*(str+k)!='\0');
return;
}
接收中断回显服务函数(板级支持包,放入串口中断服务函数中使用)
void TEST_USART_IRQHandler(void)
{
uint8_t ch;
if (__HAL_UART_GET_FLAG( &huart1, UART_FLAG_RXNE ) != RESET)//接收中断
{
ch=( uint16_t)READ_REG(huart1.Instance->DR);//读数据寄存器
WRITE_REG ( huart1.Instance->DR,ch);//写数据寄存器
}
}
三、实验内容
1.串口打印
由于cubemx已经将串口的基本配置完成,我们在该基础上进行添加即可。
当添加fputc重写函数报错时别忘了添加头文件#include "stdio.h"
总之当你需要在那个文件中使用printf时别忘记添加头文件#include "stdio.h"
在main函数中添加printf
2.串口中断实现回显
前面已经使用cubemx使能了串口中断,但是我们还未声明串口中断触发方式所以添加该语句: __HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);接收中断触发,其他触发方式可以修改函数中的参数。
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);//声明以接收中断触发
}
其他设置不变,下一步则要调用中断服务函数,及串口中断触发的入口函数
在文件stm32f1xx_it.c中可以看见串口中断服务函数,该函数内已经嵌套了一个HAL库下写好的串口中断服务函数,但当你跳进去查看会发现内部很复杂且不易改动,似乎找不到用户自行定义中断程序的位置。
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);//HAL库下的串口服务函数
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
我们可以将上诉代码中的HAL_UART_IRQHandler(&huart1);屏蔽在USART1_IRQHandler(void)函数中写入自己的程序
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
TEST_USART_IRQHandler();//上文提到的接收中断回显服务函数
/* USER CODE END USART1_IRQn 0 */
// HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
3.串口接收选择回显内容
在进行该实验建议将中断使能,找到HAL_NVIC_EnableIRQ(IRQn_Type IRQn)语句替换为HAL_NVIC_DisableIRQ(IRQn_Type IRQn)可将使能修改为失能中断即可失效。
在main.c中增加该函数
/************************
函数功能:通过接收上位机发过来的数字选择对应的接收的ch打印,如果输入了1-8其他数字则打印错误报告。
************************/
void Get_LED_CMD(void)
{
ch=getchar();
printf("接收到字符:%c\n",ch);
switch (ch)
{
case '1':
printf("ch=%c\r\n",ch);
break;
case '2':
printf("ch=%c\r\n",ch);
break;
case '3':
printf("ch=%c\r\n",ch);
break;
case '4':
printf("ch=%c\r\n",ch);
break;
case '5':
printf("ch=%c\r\n",ch);
break;
case '6':
printf("ch=%c\r\n",ch);
break;
case '7':
printf("ch=%c\r\n",ch);
break;
case '8':
printf("ch=%c\r\n",ch);
break;
default:
printf("ch=err is %c",ch);
break;
}
}
将该函数调用在main函数中while中轮询(别忘记将该函数声明在main函数之前,否则报错找不到)
测试结果:
以上Get_LED_CMD(void)函数中可以将switch语句中各个case选项中的printf替换为其他功能即可实现选择各种自己想要的功能,如发送‘1’开1灯,发送‘2’关1灯等…脑洞
版权声明:本文为CSDN博主「弦续北上i」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/CSDN_joker_/article/details/122291869
前言
助力于快速使用串口功能,如果想了解串口协议等知识点等请自行搜索,
这里注明串口下功能实现常用的fputc、字符串发送函数、fgetc函数等函数写法。
实验了三个例子来展示printf函数、串口中断使用、串口基本使用。
一、使用cubemx进行串口基本配置
二、说明
一般配置好串口我们就可以实验使用串口向上位机发送内容了,即使用板子与PC端串口调试助手或者其他设备进行信息收发。
而进行信息发送一般使用HAL库自带的发送函数HAL_UART_Transmit
另一种方法便是调用C库中的printf打印函数,而该函数是依照fputc实现的,因此需要重写该函数才可以使用printf函数。而scanf函数是依靠fgetc完成的
下面常用函数详细说明这里不做赘述,喜欢自行查阅资料
重写fputc代码
int fputc(int ch,FILE * fp)
{
HAL_UART_Transmit(&huart1,(uint8_t * )&ch,1,0xffff);
return ch;
}
**重写fgetc实现程序可调用scanf及getchar等函数**
int fgetc(FILE *f)
{
int ch;
/* 等待串口输入数据 */
while (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) == RESET);
HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return (ch);
}
注意:使用时别忘记勾选微库选项,否则printf 不起作用
注意:使用时别忘记勾选微库选项,否则printf 不起作用
注意:使用时别忘记勾选微库选项,否则printf 不起作用
字符串发送函数
void Usart1_String(char *str)
{
int k=0;
do
{
HAL_UART_Transmit(&huart1,(uint8_t * )(str+k),1,0xffff);
k++;
}
while(*(str+k)!='\0');
return;
}
接收中断回显服务函数(板级支持包,放入串口中断服务函数中使用)
void TEST_USART_IRQHandler(void)
{
uint8_t ch;
if (__HAL_UART_GET_FLAG( &huart1, UART_FLAG_RXNE ) != RESET)//接收中断
{
ch=( uint16_t)READ_REG(huart1.Instance->DR);//读数据寄存器
WRITE_REG ( huart1.Instance->DR,ch);//写数据寄存器
}
}
三、实验内容
1.串口打印
由于cubemx已经将串口的基本配置完成,我们在该基础上进行添加即可。
当添加fputc重写函数报错时别忘了添加头文件#include "stdio.h"
总之当你需要在那个文件中使用printf时别忘记添加头文件#include "stdio.h"
在main函数中添加printf
2.串口中断实现回显
前面已经使用cubemx使能了串口中断,但是我们还未声明串口中断触发方式所以添加该语句: __HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);接收中断触发,其他触发方式可以修改函数中的参数。
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);//声明以接收中断触发
}
其他设置不变,下一步则要调用中断服务函数,及串口中断触发的入口函数
在文件stm32f1xx_it.c中可以看见串口中断服务函数,该函数内已经嵌套了一个HAL库下写好的串口中断服务函数,但当你跳进去查看会发现内部很复杂且不易改动,似乎找不到用户自行定义中断程序的位置。
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);//HAL库下的串口服务函数
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
我们可以将上诉代码中的HAL_UART_IRQHandler(&huart1);屏蔽在USART1_IRQHandler(void)函数中写入自己的程序
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
TEST_USART_IRQHandler();//上文提到的接收中断回显服务函数
/* USER CODE END USART1_IRQn 0 */
// HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
3.串口接收选择回显内容
在进行该实验建议将中断使能,找到HAL_NVIC_EnableIRQ(IRQn_Type IRQn)语句替换为HAL_NVIC_DisableIRQ(IRQn_Type IRQn)可将使能修改为失能中断即可失效。
在main.c中增加该函数
/************************
函数功能:通过接收上位机发过来的数字选择对应的接收的ch打印,如果输入了1-8其他数字则打印错误报告。
************************/
void Get_LED_CMD(void)
{
ch=getchar();
printf("接收到字符:%c\n",ch);
switch (ch)
{
case '1':
printf("ch=%c\r\n",ch);
break;
case '2':
printf("ch=%c\r\n",ch);
break;
case '3':
printf("ch=%c\r\n",ch);
break;
case '4':
printf("ch=%c\r\n",ch);
break;
case '5':
printf("ch=%c\r\n",ch);
break;
case '6':
printf("ch=%c\r\n",ch);
break;
case '7':
printf("ch=%c\r\n",ch);
break;
case '8':
printf("ch=%c\r\n",ch);
break;
default:
printf("ch=err is %c",ch);
break;
}
}
将该函数调用在main函数中while中轮询(别忘记将该函数声明在main函数之前,否则报错找不到)
测试结果:
以上Get_LED_CMD(void)函数中可以将switch语句中各个case选项中的printf替换为其他功能即可实现选择各种自己想要的功能,如发送‘1’开1灯,发送‘2’关1灯等…脑洞
版权声明:本文为CSDN博主「弦续北上i」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/CSDN_joker_/article/details/122291869
暂无评论