基于HAL库的stm32f103c8t6 串口通信实验(中断方式)

目录

一、STM32CubeMX生成工程

    1.  选择stm32f03c8t6芯片

         2.  配置RCC

          3. 配置sys

          4. 配置UART1

          

5.  配置时钟

       6. 工程配置

二、串口中断函数介绍(以串口1为例)

  1. void USART1_IRQHandler(void);

   2. void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)

  3. HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

 4. HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)

 三、串口中断程序思路与编写

  1.  程序思路

  2. 程序编写

         1. 接收回调函数编写

          2. 主函数编写

 四、运行效果,仿真计算波特率

 1. 实物效果

  2. 仿真

五、总结与参考


一、STM32CubeMX生成工程

    1.  选择stm32f03c8t6芯片

0f78bb15158149009d0471dab7a785d9.png

         2.  配置RCC

51253c5c996f475da0d72c27108e2a88.png

          3. 配置sys

34d0c22ba06a413b87bdb2e848eba8b9.png

          4. 配置UART1

6113098f54424707b4ebb3050f0f4ebd.png

1892bde9772048ceafed645945df758e.png

          

5.  配置时钟

86536071cf9649d0a3de44597c0bfa2b.png

       6. 工程配置

2297c5f129624f6ea7d897fc17976905.png

 7a6401756faf4bb1ae5368cccd3e9493.png 最后点击生成代码即可 

二、串口中断函数介绍(以串口1为例)

    一般流程:

d0958841aa8c471497c23e84963a50e6.png

  1. void USART1_IRQHandler(void);

         当发生中断的时候,程序就会执行中断服务函数。然后我们在中断服务函数中编写们相应

的逻辑代码即可。 

          该函数在stm32f1xx.it.c里面,可以查看一下该函数定义:

fdfe6af416724d3cb175afd2e0ba18bb.png

       可以看出,当串口1产生中断,就会进入该函数,该函数内部可以自己定义内容,默认的是调用HAL_UART_IRQHandler(&huart1)函数,因此我们在编写逻辑代码的时候,可以在后者函数中实现。

   2. void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)

         该函数只有一个入口参数就是 UART_HandleTypeDef 结构体指针类型的串口句柄 ,是用来指明是哪个串口的触发中断。该函数一般在中断服务函数中调用,作为串口中断处理的通用入口。也就是说,真正的串口中断处理逻辑我们会最终在函数HAL_UART_IRQHandler 内部执行。该函数定义在stm32f1xx.hal_uart.c里面,该函数的功能是对接收到的数据进行判断和处理  判断是发送中断还是接收中断,然后进行数据的发送和接收。

53992ef00eda419ba70fe3ceb1c7b49d.png

  3. HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

      第二步中可以判断是接收信息产生中断还是发送信息产生中断,从而调用对应的中断函数,该函数就是接收中断函数,该函数的功能是将串口接收到大小为RXBUFFERSIZE的8bit数据保存到地址为 aRxBuffer的地方。

      因此在使用该函数的时候,需要知道接收的大小,还需要定义一个数组来保存接收到的值,如:

uint8_t size=5;
char ReBuff[5];
HAL_UART_Receive_IT(&huart1, (uint8_t *)&ReBuff,size); 

这样就将接收端到的五个8bit信息保存到Rebuff里面,但是这里有些不足,当不知道发送端发送的信息大小时,无法填写size的大小,解决此办法的方法是重写printf 和scanf函数。

调用该函数后,标示接收结束,进入回调函数HAL_UART_RxCpltCallback函数进行对应处理。

 4. HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)

      该函数的功能是通过串口发送大小为Size的字符数据,以中断模式发送数据。函数会检查UART的状态,如果当前有正在进行的发送操作,则返回忙碌状态。然后,它会检查传入的数据缓冲区指针和数据大小是否合法,如果不合法,则返回错误状态。如果参数合法,函数会设置UART句柄结构体中的成员变量,并根据UART的FIFO模式和数据长度选择相应的中断服务程序的函数指针,并使能相应的中断。最后,函数返回状态值表示发送操作的启动状态。

     同样,如果使用串口1发送数据可以如下定义:

uint8_t size=5;
char SendBuff[5]="abcde"
HAL_UART_Transmit_IT(&huart1, (uint8_t *)&SendBuff,size); 

 三、串口中断程序思路与编写

  1.  程序思路

        STM32系统给上位机(win10)连续发送“hello windows!”;当上位机给stm32发送字符“stop”后,stm32暂停发送“hello windows!”;发送一个字符“start”后,stm32继续发送。

         单片机首先需要开启接收中断,即调用HAL_UART_Receive_IT函数,当单片机接收到数据完成后,就调用中断回调函数HAL_UART_RxCpltCallback,可以编写逻辑,判断接收的字符是否为start,如果是就通过中断给PC机发送一个字符start,并置flag=1(在主函数循环中,flag=1,每隔1s给PC发送一次“Hello Windows!\n”),如果是stop,置flag=0。

  2. 程序编写

         1. 接收回调函数编写

	void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)
	{
	  if(StringCompare(ReBuff,start)==1)
		{
			flag=1;
	    HAL_UART_Transmit_IT(&huart1,(uint8_t *)start,5);
		}
		else if(StringCompare(ReBuff,stop)==1)
		{
		  flag=0;
			HAL_UART_Transmit_IT(&huart1,(uint8_t *)stop,5);
		}
		HAL_UART_Receive_IT(&huart1, (uint8_t *)&ReBuff,5); 
	}
}

          2. 主函数编写

uint8_t flag;
char ReBuff[5]; 
char SendBuff[16]="Hello Windows!\n"; 
char start[5]="start";
char stop[5]="stop ";
void SystemClock_Config(void);
int StringCompare(char rcData[5],char rcData2[5]){
	for(uint8_t i = 0 ; i < 5 ; i++){
		if (rcData[i] != rcData2[i]) return 0;
	}
	return 1;
}
int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
	HAL_UART_Receive_IT(&huart1, (uint8_t *)&ReBuff, 5); 
  while (1)
  {
    if(flag==1)
		{
		  HAL_UART_Transmit_IT(&huart1,(uint8_t *)SendBuff,16);
			HAL_Delay(1000);
		}
}
}

 四、运行效果,仿真计算波特率

 1. 实物效果

0e3f8679d5d04b53a95574edf56c1c0e.gif

  2. 仿真

         仿真查看时序和波特率

         修改一下主函数的循环

  while (1)
  {

		  HAL_UART_Transmit_IT(&huart1,(uint8_t *)SendBuff,16);
			HAL_Delay(1000);
}

    仿真查看波形需要修改一下源码,直接在while1中调用流水灯程序,查看电平持续时间,仿真需要的MDK配置:

ac0a2abb1c0f40fabd543f7b39a5c405.png

  f0d60eae12f94911b572131ce51aafed.png

 波形:

291ee9163da144d084ac6c0102625d3d.png   输出:

a3fea92e3b494ac59794ab91f27aca29.png

由于发送了160个bit,那么波特率为:

d60607ae313644b0b3e90b16c35703f8.png

  这里与我们设置的波特率115200误差相差1500hz

五、总结与参考

         1. 通过该实验,完成了中断方式的串口通信,掌握了中断串口方式配置的流程,还有一些中断的函数。

         2. 实验结果分析:从实物效果,通过串口调试助手的方式,和我们设想的目标一样,当发送start时,开始通信,发送stop时,单片机就停止给PC机发送信息。实物效果还是很明显的。通过仿真的方式,查看仿真输出,的确是和我们的结果是一样的。那么可以判断其时序图也是正确的,但是在这上面不好看出具体的某一个字符。其波特率的计算方式是通过计算发送16个字符,即160个bit总共花费时间,通过上面的标线来查看,误差还是很大,相差1500hz,可能是仿真本身存在的问题,或者在标线的时候没有很准确。

         3. 该方式相比之前的轮询方式,占用CPU资源低,效率高。

   参考:

STM32 HAL库函数——HAL_UART_Transmit_IT()详解-优快云博客

STM32学习笔记-SMT32使用HAL库UART中断方式使用_hal_uart_rxcpltcallback_楚云歌的博客-优快云博客

源码下载:

交流群 :456948834

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值