Bootstrap

浅聊STM32通信协议与专有名词

引言

对于很多人来说引脚角标,引脚含义非常模糊,只能靠网上的教程接线。

也对于很多人来说,通信协议约等于移植现成代码。

但是对于前沿设备,前言元件,大家有没有想过自己去独立完成!而不是漫天找资料,就算找到资料大概率也会就已出现资料付费的窘境!但在你买完代码后会发现,其实没有你想的那么复杂与惊艳。

那么今天我将以U串口通信为例带领大家学一学如何构建我们自己的库!

名词解释

TX:发送数据

RX:接收数据

SW_RX

SW_RX:数据接收(内部数据接收)(无外部引脚) 

硬件按控制流

硬件控制流一般用在串口通信上,他的模块是最典型的特征就是出现了RTS与CTS。它的作用就和名字一样,通过硬件信号来控制数据的传输数量与速度!!!为什么要这么做呢,为什么要通过硬件信号来控制信号传输呢!这就涉及到了“竞争与冒险”,没事,没有学过数电不要怕。我简单来说下吧:

竞争与冒险

这个电路我们当然知道结果应该是“0”,但是在实际生活中!这两个信号并不会同时到达我们的与门!他们的波形之间会有延迟,导致到与门的信号并不相反了!!!

 

从而产生一段时间仅微秒级的逻辑错误!!!!!!这就是“竞争与冒险”

所以我们硬件控制流做到了当所有信号全部到达与门时,才进行逻辑运算。这样子就消除了“竞争与冒险”

那么就好解释这两个引脚信号了:

RTS:request to send 请求发送:当引脚被拉为高电平时开始发送信号。

nRTTS:这里的n代表的时逻辑相反!!!!因此引脚拉低才开始发送信号。

CTS:clear to send :清晰(允许)发送:当引脚拉高时,允许发送的信号进入我的缓冲区,当拉低时不接受信号。

nCTS:逻辑相反即可。

SCLK:同步时钟引脚。

但是在我们的STM32中很明显没有后面三个引脚,所以我们的STM32的USART是异步通信,单信号传输。不用担心上面出现的情况。

另外在配置时我们一定要考虑,我们使用的USART挂在位置!!APB2 时钟频率最大72MHz而APB1时钟频率最大才36MHz。很多人移植什么都不看所有工作频率都是50MHz是非常错误的!

通信协议

通信协议才是进行通信的核心,人说人话,猫说猫语,所以只有把协议具象化才能进行目标通信!

所以USART的通信协议如下:

附带官网的配置教程:

 

但是要知道,既然STM32能进行USART通信,就一定有相关的固件库函数!

 

所以,他和GPIO口的初始化还有啥区别!但因为有标志位操作所以少不了中断服务函数!

初始化 

void usart1_init(void)
{
USART_InitTypeDef usart1;
GPIO_InitTypeDef gpio1;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);	//开启USART1的时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOA的时钟
  gpio1.GPIO_Mode=GPIO_Mode_AF_PP;
	gpio1.GPIO_Pin=GPIO_Pin_9;
	gpio1.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&gpio1);
	gpio1.GPIO_Mode=GPIO_Mode_IPU;
	gpio1.GPIO_Pin=GPIO_Pin_10;
	gpio1.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&gpio1);
	usart1.USART_BaudRate=9600;
	usart1.USART_HardwareFlowControl=USART_HardwareFlowControl_None ;
	usart1.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
	usart1.USART_StopBits=USART_StopBits_1;
	usart1.USART_WordLength=USART_WordLength_8b;
  usart1.USART_Parity=USART_Parity_No;
	USART_Init(USART1, &usart1);
	NVIC_InitTypeDef nvic1;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	nvic1.NVIC_IRQChannel= USART1_IRQn;
	nvic1.NVIC_IRQChannelCmd=ENABLE;
	nvic1.NVIC_IRQChannelPreemptionPriority=1;
	nvic1.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&nvic1);
	USART_ClearFlag(USART1, USART_FLAG_RXNE);
	USART_ITConfig(USART1, USART_FLAG_RXNE,ENABLE);
	USART_Cmd(USART1, ENABLE);
}

全部配置好我们就需要根据协议来写三种函数:接收函数,发送函数,中断函数

并且这些函数的基本体我们库函数中都有!!!不需要你自己去写寄存器!!!

两个头文件

#include <stdio.h>

stdio.h 是标准输入输出(Standard Input Output)的头文件。它包含了进行输入输出操作的函数声明,比如 printf() 用于向标准输出(通常是屏幕)打印格式化的字符串,scanf() 用于从标准输入(通常是键盘)读取格式化的输入,以及文件操作函数如 fopen()fread()fwrite()fclose() 等。基本上,任何与输入输出相关的操作,都可能需要包含 stdio.h 头文件。

#include <stdarg.h>

stdarg.h 是标准参数(Standard Arguments)的头文件。这个头文件提供了对可变参数(即函数参数的数量和类型在编译时未知)的支持。这在编写像 printf() 这样可以接受任意数量和类型参数的函数时非常有用。通过 stdarg.h 提供的宏和类型定义,程序可以遍历并访问传递给函数的可变参数列表。这个头文件主要与宏 va_listva_start()va_arg(), 和 va_end() 相关联,这些宏允许程序以类型安全的方式访问可变参数列表中的参数。

简而言之,#include <stdio.h> 用于包含输入输出操作相关的函数声明,而 #include <stdarg.h> 用于支持编写可以接受可变数量参数的函数。这两个头文件在C语言编程中都非常常用。

所以我们在使用Printf函数时均需要调用!

void usar1_s1(uint16_t byte)
{
USART_SendData(USART1, byte);
while(USART_GetITStatus(USART1, USART_FLAG_RXNE)==RESET);
}
void usart1_s(uint8_t *arry,uint16_t legth)
{
	uint16_t i=0;
for(i=0;i<legth;i++)
	{
     usar1_s1(arry[i]);
	}
}

void usart1_st(uint8_t *string)
{
	uint16_t i;
for(i=0;string[i]!='\0';i++)
{
usar1_s1(string[i]);
}

}

中断函数

void USART1_IRQhandler(void)
{
	static uint8_t RXdata;
	static uint8_t PACK=0;
if(USART_GetITStatus(USART1, USART_FLAG_RXNE)==SET)
{
uint8_t RXdata=USART_ReceiveData(USART1);
RXPACK[PACK]=RXdata;
usar1_s1(RXPACK[PACK]);	
PACK++;	
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}

printf函数 

我们可以重定义也可以自己构建!

int fputc(int ch, FILE *f)
{
	usart_s1(ch);			//将printf的底层重定向到自己的发送字节函数
	return ch;
}
/**
  * 函    数:自己封装的prinf函数
  * 参    数:format 格式化字符串
  * 参    数:... 可变的参数列表
  * 返 回 值:无
  */
void usart1_Printf(char *format, ...)
{
	char String[100];				//定义字符数组
	va_list arg;					//定义可变参数列表数据类型的变量arg
	va_start(arg, format);			//从format开始,接收参数列表到arg变量
	vsprintf(String, format, arg);	//使用vsprintf打印格式化字符串和参数列表到字符数组中
	va_end(arg);					//结束变量arg
	usart1_st(String);		//串口发送字符数组(字符串)
}

这次你已经自主完成了USART串口通信的库! 

 

 

 

;