一、通信的意义
首先,我们了解一下什么是通信,为什么需要通信,简单来讲,就是通过通信可以实现更多单靠STM32芯片本身完成不了的工作,比方蓝牙,WIFI功能的实现,显然只靠STM32本身是不行的,这时候就需要借助通信来实现芯片、模块之间的连接,用以进行硬件拓展,从而达到功能多样化。STM32的通信类别有如下:(下图参考取自江科协)
全双工指一般有两条数据线,即输入输出,半双工即一根数据线实现输入输出,还有一种单工,只能单向传输数据。同步时钟可以通过时钟信号进行采样,异步时钟则需要通过采样频率进行接收发送。单端信号供地需要接一起,差分信号通过电压差实现通信,提高抗干扰特性,点对点直接传送数据,多设备需要进行寻址操作。
串口通讯是一种点对点的通讯方式,实现两设备之间的通信。
我们了解一下USART串口通信。
首先STM32F103C8T6包含USART1,USART2和USART3三个资源。除USART1在APB2总线上,其余在APB1总线上。接下来是USART的部分引脚图。
引脚必须按照以上定义进行设计。
接下来来看一看USART如何配置。
二、USART基本配置说明
如上面所讲,使用USART需要开启对应的时钟,使用USART1开启APB2时钟,然后是需要使用的GPIO端口的配置,这里不再赘述。接下来就是USART的配置了。
这里USART的配置中,波特率需要和另一设备保持一致才能进行通信,否则可能导致无法通信,另外USART模式选择中,如果只需要发送数据就只要USART_Mode_Tx就行,只要接收就USART_Mode_Rx就行,都需要的话用或操作即可(|),其余的可自行了解,一般不进行改动了。这样USART的基本配置就完成了。
#include "stm32f10x.h" // Device header
void Serial_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//开启USART1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate=9600;//设置波特率
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//硬件流控制
USART_InitStructure.USART_Mode=USART_Mode_Tx;//USART模式
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_Cmd(USART1,ENABLE);
}
1.数据发送
接下来我们写一个向电脑发送数据的函数,这里使用USART_SendData进行数据的发送。第一个参数给选择的USART,第二个定义一个发送的一个变量,与函数保持一致。然后使用USART_GetFlagStatus并用while循环进行标志位清零,这样就可以了,再在主函数进行声明调用即可。
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1,Byte);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//标志位自动清零
}
主函数配置如下,写一个参数例如0x56,那么编译运行按下复位键后,STM32就会向电脑发送一个56的十六位进制数。
#include "stm32f10x.h" // Device header
#include "Serial.h"
int main (void)
{
Serial_Init();
Serial_SendByte(0x56);
while(1)
{
}
}
关于串口发送更多的实用性这里不再说明,有时间专门写一篇。
2.数据接收
因为RX的引脚为PA10,串口数据接收需要重新配置GPIO口,代码如下
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIOInitstructure);
同时上面的串口模式也需要改为接收,即或上USART_Mode_Rx。
USART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
我们使用中断进行数据的接收,这里只操作一下简单的接收现象。
接下来配置一下NVIC,如下
NVIC的配置就不再赘述了。该代码放在USART_Cmd(USART1,ENABLE);的上方。
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
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的程序里,写上关于中断的串口接收通信,这一部分同样不再赘述,看注释即可
uint8_t Serial_GetRxData(void)
{
return Serial_RxData; //返回接收的数据
}
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)//判断是否是USART1的接收事件触发的中断
{
Serial_RxData = USART_ReceiveData(USART1); //读取数据寄存器,存放在接收的数据变量
Serial_RxFlag = 1; //置接收标志位变量为1
USART_ClearITPendingBit(USART1, USART_IT_RXNE); //清除标志位
}
}
主函数的话,如果标志位为1,则进入if调用Serial_GetRXData()读取接收到的数据即可。这样就获得了接收到的数据。
uint8_t RXData;
int main (void)
{
Serial_Init();
while(1)
{
if(Serial_GetRXFlag()==1)
{
RXData=Serial_GetRXData();
}
}
}
三、其他相关
关于这里的STM32与电脑的连接是通过CH340进行连接的,然后电脑端通过串口调试助手进行数据的接收显示,串口调试助手可以在网上自行下载,这里我也放一个链接。https://pan.baidu.com/s/1P-GXde1KP9wM_0qzwI2fPQ#list/path=%2F 提取码为a305
如果想显示字符的话,将十六进制数取消勾选,显示的就是字符形式了,至于数字与字符的对应是通过ASCll码表实现转换的。
关于串口发送更多的实用性这里不再说明,有时间专门写一篇。