记录7——学习stm32之实现轮询方式、中断方式及简单帧格式串口通信

一.轮询方式

轮询方式就是不断去访问一个信号的端口,看看有没有信号进入,有则进行处理。

任务

通过任务轮询方式,利用串口调试助手发送字符,若发送‘y’,则在调试助手上显示‘Received
y!‘,且LED亮;若发送’n’,则在调试助手上显示’Received
n!',LED灭;若发送其他字符,则在调试助手上显示‘Received others!’

代码实现

/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

printf、scanf函数重定向


int fputc(int ch,FILE *f)
{
	HAL_UART_Transmit (&huart2 ,(uint8_t *)&ch,1,HAL_MAX_DELAY);
	return ch;
}

int fgetc(FILE *f)
{
	uint8_t ch;
	HAL_UART_Receive (&huart2 ,(uint8_t *)&ch,1,HAL_MAX_DELAY);
	return ch;
}


/* USER CODE BEGIN PV */
uint8_t RecDate;//接收缓冲区

/* USER CODE END PV */
/* USER CODE BEGIN 2 */
	printf ("UART Retarget:\r\n");
  /* USER CODE END 2 */

while中写入

if(scanf("%c",&RecDate )==1)
		{
			if(RecDate =='y')
			{
				printf ("Received y!\r\n");
				HAL_GPIO_WritePin (GPIOC ,GPIO_PIN_13,GPIO_PIN_RESET );
			}
			else if(RecDate =='n')
			{
				printf ("Received n!\r\n");
				HAL_GPIO_WritePin (GPIOC ,GPIO_PIN_13,GPIO_PIN_SET );
			}
			else
			{
				printf ("Received others!\r\n");
			}
		}

二.中断方式

中断方式则是当输入产生的时候,产生一个触发信号告诉 STM32 有输入信号进入,需要进行处理。

任务

利用中断方式,实现定长数据的收发。

代码实现

/* USER CODE BEGIN PD */
#define LENGTH 10
/* USER CODE END PD */

/* USER CODE BEGIN PV */
uint8_t RxBuffer[LENGTH];
uint8_t RxFlag = 0;//接收完成标志
/* USER CODE END PV */
/* USER CODE BEGIN 2 */
	printf("Please enter 10 characters:\r\n");
	HAL_UART_Receive_IT(&huart2 ,(uint8_t*)RxBuffer ,LENGTH);

  /* USER CODE END 2 */
/* USER CODE BEGIN 3 */
		if(RxFlag == 1)
		{
			RxFlag=0;
			printf ("Recevie!");
			HAL_UART_Transmit_IT(&huart2 ,(uint8_t*)RxBuffer ,LENGTH);
		}
  
  /* USER CODE END 3 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART2)
	{
		RxFlag = 1;
		HAL_UART_Receive_IT(&huart2 ,(uint8_t*)RxBuffer ,LENGTH);
	}
}

三. 简单的帧格式

帧格式的组成:帧头 设备码 功能码 帧尾

任务

利用简单帧格式,当发送aa 01 01 55时,点亮LED灯,当发送aa 01 00 55时,熄灭LED灯。

代码实现

/* USER CODE BEGIN PV */
uint8_t RxBuffer[4];//接收缓冲区
uint8_t RxFlag=0;//接收完成标志:0--接收未完成;1--接收完成
uint8_t ErrFlag=0;//指令错误标志:0--指令正确;1--指令错误

/* USER CODE END PV */
/* USER CODE BEGIN 2 */
	printf ("********************\r\n");
	printf ("head->0xaa,device->0x01,operation->0x00/0x01,tail->0x55\r\n");
	HAL_UART_Receive_IT(&huart2 ,(uint8_t*)RxBuffer ,4);//使能接收中断

  /* USER CODE END 2 */
    /* USER CODE BEGIN 3 */
		if(RxFlag == 1)
		{
			RxFlag = 0;//清除标志位
			if(RxBuffer[0] == 0xaa && RxBuffer[3] == 0x55 )//判断帧头帧尾
			{
				if(RxBuffer[1] == 0x01)//判断设备码
				{
					if(RxBuffer[2] == 0x01) //判断功能码
					{
						HAL_GPIO_WritePin (GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
						printf ("open!\r\n");
					}
					else if (RxBuffer[2] == 0x00) 
					{
						HAL_GPIO_WritePin (GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
						printf ("close!\r\n");
					}
					else ErrFlag = 1;//功能码错误,置位错误标志(else只和最近的if进行对应噢!)
				}
				else ErrFlag = 1;//设备码错误,置位错误标志
			}
			else ErrFlag = 1;//帧头、尾错误,置位错误标志

			if(ErrFlag == 1)
			{
				printf ("Wrong\r\n");
			}
			//清除接收缓冲区和错误标志,准备下一步接收
			RxBuffer [0] = 0;
			RxBuffer [1] = 0;
			RxBuffer [2] = 0;
			RxBuffer [3] = 0;
			RxFlag = 0;
			ErrFlag = 0;
		}
  }
  /* USER CODE END 3 */
/* USER CODE BEGIN 4 */
void  HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART2)
	{
		RxFlag = 1;
		HAL_UART_Receive_IT(&huart2 ,(uint8_t*)RxBuffer ,4);
	}
}
int fputc (int ch,FILE *f)
{
	HAL_UART_Transmit (&huart2 ,(uint8_t *)&ch,1,HAL_MAX_DELAY);
	return ch;
}

int fgetc(FILE *f)
{
	uint8_t ch;
	HAL_UART_Receive (&huart2 ,(uint8_t *)&ch,1,HAL_MAX_DELAY);
	return ch;
}

/* USER CODE END 4 */
  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 好的,这是一个简单的 PMBus 通信协议代码示例,使用轮询方式实现: ``` #include <stdio.h> #include <stdbool.h> #define PMBUS_ADDRESS 0x5A // PMBus 设备地址 #define PMBUS_CMD_READ_VOUT 0x8B // PMBus 读取输出电压命令 // 初始化 PMBus 通信 void pmbus_init(void) { // 省略初始化代码 } // 发送 PMBus 命令并读取返回数据 bool pmbus_send_command(unsigned char cmd, unsigned char *data, int len) { // 省略 I2C 发送命令和读取数据代码 return true; // 返回 true 表示命令执行成功,false 表示失败 } int main(void) { pmbus_init(); // 初始化 PMBus 通信 while (1) { unsigned char data[2]; // 用于存储读取到的数据 if (pmbus_send_command(PMBUS_CMD_READ_VOUT, data, 2)) { // 读取输出电压成功,处理读取到的数据 float vout = (data[0] + (data[1] / 256.0)) * 0.0016; printf("Output voltage: %.2f V\n", vout); } else { // 读取输出电压失败,处理错误 printf("Failed to read output voltage\n"); } // 省略其他代码 } return 0; } ``` 该代码实现轮询的 PMBus 通信,使用 `pmbus_send_command` 函数向 PMBus 设备发送命令并读取返回数据,从而实现了 PMBus 通信协议。注意代码中的 `pmbus_init` 函数和 `pmbus_send_command` 函数需要根据实际情况 ### 回答2: 首先,需要了解一些关于PMBus通信协议的基本知识。 PMBus(Power Management Bus)是一种用于电源管理系统的开放式通信协议。它使用两根线(SCL和SDA)进行单主从多从的串行通信。 下面是使用C语言编写的一个PMBus通信协议示例(使用轮询方式,不使用中断): ```c #include <stdio.h> #include <stdint.h> #define PMBUS_ADDRESS 0x12 // 要通信的PMBus从设备地址 void pmbus_send_byte(uint8_t byte) { // 发送一个字节 // 这里使用硬件SPI或I2C函数实现发送操作 } uint8_t pmbus_receive_byte() { // 接收一个字节 // 这里使用硬件SPI或I2C函数实现接收操作 } void pmbus_start() { // 发送起始信号 pmbus_send_byte(0x00); // 起始标志 pmbus_send_byte(PMBUS_ADDRESS << 1); // 从设备地址,左移1位,加上写标志位 } void pmbus_stop() { // 发送停止信号 // 这里使用硬件SPI或I2C函数实现停止操作 } void pmbus_send_command(uint8_t command) { // 发送命令字节 pmbus_send_byte(command); } uint8_t pmbus_receive_response() { // 接收应答字节 return pmbus_receive_byte(); } int main() { // 初始化硬件SPI或I2C // 进行PMBus通信 pmbus_start(); // 发送起始信号 pmbus_send_command(0x01); // 发送命令字节 uint8_t response = pmbus_receive_response(); // 接收应答字节 pmbus_stop(); // 发送停止信号 // 处理接收到的应答字节,例如打印或其他操作 printf("Response: %x\n", response); return 0; } ``` 请注意,以上示例代码只是一个简单的PMBus通信协议示例,仅包括了通信的基本操作,实际使用时需要根据具体的硬件和芯片进行适配和修改。 另外,PMBus通信协议还涉及到具体的命令字节和数据格式,根据需要还需要进行命令字节和数据的解析和处理。具体的命令字节和数据格式请参考相关的PMBus通信协议文档。 ### 回答3: STM32G484是一款高性能的32位ARM Cortex-M4处理器微控制器,拥有多个外设接口,包括支持PMBus通信协议的USART串行接口。下面是一个使用C语言编写的基于轮询方式的PMBus通信协议示例: 1. 首先,配置USART串行接口作为PMBus通信的主机。 2. 初始化PMBus相关的寄存器和变量。 3. 在主循环中,首先发送PMBus总线的起始信号(START)。 4. 延时一段时间,确保PMBus总线上的设备已经准备就绪。 5. 发送PMBus设备的地址和读/写位。 6. 等待传输完成标志位(TC)置位,表示地址和读/写位已发送完毕。 7. 如果是读操作,发送要读取的寄存器地址。 8. 等待传输完成标志位(TC)置位,表示寄存器地址已发送完毕。 9. 发送PMBus读取命令。 10. 等待传输完成标志位(TC)置位,表示读取命令已发送完毕。 11. 等待数据接收完成标志位(RXNE)置位,表示数据已接收完毕。 12. 读取接收到的数据。 13. 处理接收到的数据,根据PMBus协议进行解析。 14. 如果是写操作,发送要写入的寄存器地址。 15. 等待传输完成标志位(TC)置位,表示寄存器地址已发送完毕。 16. 发送要写入的数据。 17. 等待传输完成标志位(TC)置位,表示数据已发送完毕。 18. 接收和处理ACK信号,判断是否写入成功。 19. 继续下一个PMBus操作或者进入等待状态。 请注意,在此示例中,我们仅包含了PMBus通信的基本步骤,具体的协议解析和处理需要根据实际需求进行进一步的开发和完善。同时,轮询方式是一种简单直接的通信方式,但在实际应用中可能会影响系统的响应性能。如果有需要,可以考虑使用中断方式来增强系统的实时性和效率。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Drawing Ting

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值