32入门-串口通信-发送和接收数据

本文详细介绍了STM32的串口通信,包括全双工、半双工和单工通信方式,USART外设的同步/异步收发器,波特率设置,引脚复用以及初始化流程。还涉及了硬件电路中的TX、RX、GND连接,软件部分的数据发送和接收,以及printf函数在串口打印中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

通信方式

硬件电路

软件部分

USART外设(同步/异步收发器)

波特率

引脚复用

初始化基本流程

发送

接收

语言简述

常用的函数

使用的结构体

引脚模式

打印数据的三种方法

使用printf


在实际的串口中,只能发送二进制数,也就是十六进制的最直接数据。如果想发送字符,就需要一个数据->字符的映射表(如ASCII表)

通信方式

全双工:两根线,数据的发送和接收互不影响。

半双工:一根线,一发一收。

单工:数据只能从一个设备到另一个设备。

举例子->

全双工:打电话。半双工:对讲机。单工:广播

有时钟线,同步通信

无时钟线,异步,甚至需要添加帧头帧尾使数据对齐。

单端信号(电平):它们引脚的高低电平都是对GND的电压差,所以单端通信的双方都必须共地,就是把GND接到一起。

而差分信号则不用。

硬件电路

TX、RX、GND是必须要接的,而VCC若两个设备都有独立供电,可以不接。 

使用TTL电平。

软件部分

 俩种形式

 有校验位就是9位数据位,没有就是8位。

 数据低位先行

预发送数据 0x0f    (H)0000 1111(L)

L->H

检验位采用奇偶校验的方法(如果数据错了可以丢弃或者重传)

        校验3法 : 无校验 奇校验 偶校验

  1. 无校验 如1帧10位 没有校验位
  2. 奇校验 包括校验位会出现奇数个1
  3. 偶校验 包括校验位会出现偶数个1

如 奇校验 0000 1111 总共4个1,于是校验位就会补一个1,保证其是奇数。

奇偶校验只能保证一定程度上的验出率,更高级还是得了解CRC校验。

USART外设(同步/异步收发器)

【注意】USART1是挂在APB2总线上的,而其他是在APB1总线上的。

STM32F103C8T6 USART资源 :USART1(APB2)、USART2、USART3(APB1)

开启时钟的时候需要控制。

波特率

波特率发生器就是分频器,APB时钟进行分频,得到发送和接收移位的时钟。

USART1挂载在APB2【中文参考手册---系统架构】,所以就是PCLK2的时钟,一般是72M。其余的是APB1,也就是36M。

然后进行分频。晶振除以一个USARTDIV的分频系数,分频完之后还要再除以16

引脚复用

   

初始化基本流程

参考中文手册USART部分

发送

接收

语言简述

  1. 开启外设,开启时钟,把需要用的USART和GPIO的时钟打开
  2. GPIO初始化,把TX配置成复用输出,RX配置成输出
  3. 配置USART,直接使用一个结构体
  4. 如果只需要发送功能,直接开启USART初始化就结束了。如果还需要接收还需要开启中断。在开启中断之前,再加上ITConfig和NVIC的代码。

常用的函数

使用的结构体

USART_InitTypeDef、

USART_ClockInitTypeDef【同步时钟,但是我们一般使用的是异步通信,所以不怎么用】

引脚模式

        TX是USART外设控制输出脚,所以选择复用推挽输出(GPIO_Mode_AF_PP);

        RX是USART外设数据输入脚,所以选择输入模式。输入模式并不分什么普通输入、复用输入,一根线只能有一个输出,但可以有多个输入。所以输入脚外设、GPIO都可以使用。RX一般是浮空输入or上拉输入。因为串口波形空闲状态是高电平,所以不采用下拉输入。

void USART_Config(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	//GPIO配置控制
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;		//TX
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;		//RX
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//USART配置控制
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1, &USART_InitStructure);
	
	//接收使能,接受不为空的时候产生中断
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);	
	
	//NVIC配置控制
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	USART_Cmd(USART1, ENABLE);

}

ctrl+alt +space 开启联想

打印数据的三种方法

        1、printf

        2、sprintf

        3、封装sprintf(进阶学习--->C语言可变参数)

使用printf

 还要进行重定向导入 stdio.h

printf->单。意思是只有一个串口可以使用。

sprintf->多。可以指定打印位置,不涉及重定向的东西。

格式+内容。 

 MicroLIB是keil为嵌入式平台优化的精简库,在keil里面使用printf函数要使用这个,然后还需要重定向,将怕printf函数打印的东西输出到串口。先include ->stdio.h,然后重写fputc(这个是printf的底层)

public partial class Form1 : Form { public Form1() { InitializeComponent(); } SerialPort port1 = new SerialPort(); string InputData = String.Empty; delegate void SetTextCallback(string text); private void Port_Select() {//获取机器中的串口地址 string[] ports = SerialPort.GetPortNames(); foreach (string port in ports) { comboBox1.Items.Add(port); } } private void Form1_Load_1(object sender, EventArgs e) { Port_Select(); this.comboBox1.SelectedIndex = 0; this.comboBox2.SelectedIndex = 0; } private void button1_Click(object sender, EventArgs e) { if (button1.Text == "关闭串口") //当要关闭串口的时候 { port1.DiscardOutBuffer(); port1.DiscardInBuffer(); port1.Close(); button1.Text = "打开串口"; label3.Text = "串口当前状况:未打开"; comboBox1.Enabled = true; comboBox2.Enabled = true; } else if (button1.Text == "打开串口") //当要打开串口的时候 { try { port1.PortName = comboBox1.SelectedItem.ToString(); port1.BaudRate = Convert.ToInt32(comboBox2.SelectedItem); port1.DataBits = 8; port1.RtsEnable = true; port1.Open(); port1.DiscardOutBuffer(); port1.DiscardInBuffer(); button1.Text = "关闭串口"; comboBox1.Enabled = false; comboBox2.Enabled = false; label3.Text = "串口:" + comboBox1.SelectedItem.ToString() + " 波特率:" + comboBox2.SelectedItem.ToString() + " 数据位:8 "; } catch { button1.Text = "打开串口"; label3.Text = "串口:" + comboBox1.SelectedItem.ToString() + "打开失败"; MessageBox.Show("该串口无法打开"); } } } 资源中部分代码
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值