蓝桥杯物联网竞赛_STM32L071_5_串口接收&发送数据

理论:

串口采取异步通信,即不依赖时钟节拍来接收或发送数据,而是采用互相约定的波特率传输数据。

波特率与单位时间传输的比特数有关,波特率越大传输的数据越多
传输一个比特花费的时间T = 1 / 比特率

接受和发送数据的时候需要接受端和发送端:
蓝桥杯物联网竞赛_STM32L071_5_串口接收&发送数据_第1张图片
UART传输数据是一位一位的向接收端传输,为了知道何时传输,又或者为了保证传输数据的完整正确性,规定了传输协议

蓝桥杯物联网竞赛_STM32L071_5_串口接收&发送数据_第2张图片
分别为开始、数据、校验、停止,其中校验位可要可不要

传输样例:

蓝桥杯物联网竞赛_STM32L071_5_串口接收&发送数据_第3张图片
停止位取二进制数0,数据位一般有8位刚好能装下一个字符,一般的停止位是1位取值为1,校验一般不要

开发板原理图:

蓝桥杯物联网竞赛_STM32L071_5_串口接收&发送数据_第4张图片

可以出开发板有两组收发引脚,但其实真正有效的只有一组即PA2和PA3,下面详细说一下:

蓝桥杯物联网竞赛_STM32L071_5_串口接收&发送数据_第5张图片
上述是开发板中控制下载调试器部分的芯片,其一般作用就是将程序或固件加载到微处理器或微控制器,朴素的讲调试器主要作用就是将电脑代码导入到开发板的芯片中
蓝桥杯物联网竞赛_STM32L071_5_串口接收&发送数据_第6张图片

也就是说下载调试器能连接电脑STM32L071要想能与电脑上的串口小助手通信,那就必须TX,RX能与电脑相连,所以下载调试器中的芯片GD32F350C8T6上的PA9、PA10就必须先发送或者接收STM32L071传来的数据,其真正的作用是一个连接作用,即将STM32L071与电脑间接相连

而STM32L071的另外一组引脚没有与下载调试器相连所以也就没有作用

STM32L071的TX,RX与GD32F350C8T6引脚连接的部分:
蓝桥杯物联网竞赛_STM32L071_5_串口接收&发送数据_第7张图片

而SET由开发板SELECT按键控制其高低电平,高低电平能使其接通1、4引脚或3、4引脚


CubMX配置:

蓝桥杯物联网竞赛_STM32L071_5_串口接收&发送数据_第8张图片
Asynchronous: 异步通信


Keil配置:

Function.c和Function.h文件:

#include "Function.h"
#include "i2c.h"
#include "oled.h"
#include "usart.h"


void OLED_Write(unsigned char type, unsigned char data){ // 写函数
	unsigned char Write_data[2];
	Write_data[0] = type;
	Write_data[1] = data;
	HAL_I2C_Master_Transmit(&hi2c3, 0x78, Write_data, 2, 0xff);
}

void Function_OledEnable(unsigned char ms){ // Oled使能
	HAL_GPIO_WritePin(OLED_POWER_GPIO_Port, OLED_POWER_Pin, GPIO_PIN_RESET);
	HAL_Delay(ms);
	OLED_Init();
}

void Function_SendInfromation(const char * data, uint16_t len){ // 发送信息
	HAL_UART_Transmit(&huart2, data, len, 0xff);
}

void Function_ReceiveInfromation(char * data, uint16_t len){ // 接受信息
	HAL_UART_Receive(&huart2, data, len, 0xff);
}
#ifndef __FUNCTION__
#define __FUNCTION__
#include 

void OLED_Write(unsigned char type, unsigned char data);
void Function_OledEnable(unsigned char ms);
void Function_ReceiveInfromation(char * data, uint16_t len);
void Function_SendInfromation(const char * data, uint16_t len);
#endif

main.c

#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
#include "Function.h"
#include "oled.h"
#include 
void SystemClock_Config(void);

int main(void)
{
	char a[] = {4, 5, 6};
	char flag = 1;
	char b[] = {0, 0, 0};
 

  HAL_Init();


  SystemClock_Config();


  MX_GPIO_Init();
  MX_I2C3_Init();
  MX_USART2_UART_Init();
  Function_OledEnable(50);

  while (1)
  {
    
    OLED_ShowString(0, 0, "i am wining", 16);
		if(flag <= 2){
			flag ++;
		  HAL_Delay(5000);
		  Function_SendInfromation(a, strlen(a));
		  HAL_Delay(5000);
		}
  		OLED_ShowString(0, 2, "Receive:", 16);
		
		Function_ReceiveInfromation(b, 3);
		
	  if(b[0] == '@'){
		  OLED_ShowString(64, 2, b, 16);
      b[0] = '1';			
		}
		 

  }
}


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

  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** 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_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_4;
  RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
  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_PLLCLK;
  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_1) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2|RCC_PERIPHCLK_I2C3;
  PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
  PeriphClkInit.I2c3ClockSelection = RCC_I2C3CLKSOURCE_PCLK1;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != 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 */

效果:

蓝桥杯物联网竞赛_STM32L071_5_串口接收&发送数据_第9张图片

程序启动后等10s钟后发送数据:

蓝桥杯物联网竞赛_STM32L071_5_串口接收&发送数据_第10张图片

拓展:

HAL_UART_TransmitHAL_UART_Receive,在传输与接收数据的时候,都会对做一些检查,例如指针数据长度是否有效,收发是否有效,如果不合格就会返回错误,如果合格就会进入忙碌状态即利用while函数一直对数据进行转发,或者收取。

在接受数据的时候,如果未能及时接收,那么后到的数据回应超时未接收报错,然后终止操作,这就是为什么在主函数有程序抢占cpu时不能即时接收数据,最后显示的数据只有一个字符。

这种情况可以用中断串口通信解决。

你可能感兴趣的:(蓝桥杯,物联网,stm32)