基本原理
处理器与外部设备的两种通信方法
- 并行通信
原理——数据各个位同时传输
速度块,但占用引脚资源多 - 串行通信
原理——数据按位顺序传输
占用引脚资源少,但速度较慢
串行通信
按数据传送方向分类
-
单工
数据传输只支持数据在一个方向上传输 -
半双工
允许数据在两个方向上传输,但同一时间只能有一个方向的传输
是一种切换方向的单工通信 -
全双工
允许同时在两个方向上传输数据
是两个单工通信方式的结合,要求发送和接收设备都有独立的接收和发送能力
通信方式
-
同步通信
带时钟同步信号的传输 -
异步通信
不带时钟同步信号的传输
通信双方必须约定好波特率(传输的速率)
串行通信接口
串口异步通信需要定义的参数
- 起始位
- 数据位
- 奇偶校验位
- 停止位
- 波特率设置
串口相关寄存器
串口通信操作
串口设置步骤
- 串口时钟使能,GPIO 时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
- 串口复位
USART_DeInit(USART1);
- GPIO 端口模式设置
GPIO_Init(GPIOA,&GPIO_InitStrue);//输入输出模式从技术收车查
- 串口参数初始化
USART_Init(USART1,&USART_InitStrue);
- 开启中断并初始化 NVIC (需要中断时)
USART_ITConfig (USART1,USART_IT_RXNE,ENABLE);
NVIC_Init (&NVIC_InitStrue);
- 使能串口
USART_Cmd(USART1,ENABLE);
- 编写中断函数(需要中断时)
void USART1_IRQHandler(void)
- 串口数据收发
u8 ree;
ree = USART_ReceiveData;
USART_SendData(USART1,ree );
- 串口传输状态获取
USART_GetITStatus(USART1,USART_IT_RXNE)
串口有关函数
(位于stm32f10x_usart.h 和 stm32f10x_usart.c 文件)
- 使能串口时钟
RCC—reset clock controller ——复位与时钟控制器
APB2——RXD TXD 位于 APB2 总线的PA9 和 PA10 上
periph ——周围的,末梢
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1);
- 串口复位
当外设出现异常时,可以通过复位设置,实现该外设的复位,然后重新配置外设,使其重新工作
一般在系统刚开始配置外设时,复位外设
deinit——反初始化函数
把已经初始化的外设,,变回未初始化的状态
效果与 init 相反
void USART_DeInit(USART_TypeDef* USARTx);//串口复位
例——复位串口1
USART_DeInit(USART1);
- 串口参数初始化
void USART_Init(USART_TypeDef*USARTx,USART_InitTypeDef* USART_InitStruct);
两个参数
1)指定初始化的串口
2)含有初始化该串口需要参数的结构体指针
其成员变量
USART_InitStructure.USART_BaudRate = bound; //波特率;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为 8 位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口
baud——波特——数据通信速度的表示单位
parity——奇偶校验位——传输和储存的数据中的增加的额外一位——校验错误
需要初始化的参数
波特率,字长,停止位,奇偶校验位,硬件数据流控制,收发模式
- 数据接收与发送
接受函数
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
读取 USART_DR 寄存器接收的数据
发送函数
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
向 USART_DR 写入一个数据
接收和发送时通过 USART_DR(数据寄存器)来实现
该寄存器含有 TDR 和 RDR 两个寄存器
向该寄存器写数据,串口会自动发送
接收的数据,存于该寄存器内
- 串口状态
利用 USART_SR (状态寄存器)读取
读取串口状态函数
FlagStatus USART_GetFlagStatus(USART_TypeDef*USARTx, uint16_t USART_FLAG);
flag——旗帜
status——状态
两个参数
1)要读取的串口
2)判断寄存器状态
RXNE——接受缓冲器非空
TC——发送完成
例
判断是否非空
USART_GetFlagStatus(USART1, USART_FLAG_RXNE);
判断是否发送完成
USART_GetFlagStatus(USART1, USART_FLAG_TC);
在 FLAG 后加了假设的词,通过返回值,判断情况
- 串口使能
USART_Cmd(USART1, ENABLE);
enable——可以,使能
- 开启串口响应中断
使能串口中断的函数
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState)
config——配置
两个参数
1)确定使能的串口
2)标志使能串口的类型
串口的中断类型有很多,需要选择使能的中断类型
例
当即接收到数据时(REXN √),要产生中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断,接收到数据中断
当发送数据结束后(TC √),要产生中断
USART_ITConfig(USART1,USART_IT_TC,ENABLE);//开启中断,当发送结束后中断
- 获取相应中断状态
当使能了某个中断后,该中断发生了,就会设置状态寄存器中的某个标志位
判断中断是哪种中断使用的函数
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)
两个参数
1)要获取的串口
2)判断那种中断
例
使能了串口发送完成的中断(TC),如果中断发生了
在中断处理函数中调用该函数,判断是否串口发送完成中断
USART_GetITStatus(USART1, USART_IT_TC)
如果返回 set 则中断发生
代码
#include "stm32f10x.h"
void My_USART1_Init()//用来设置的函数,避免main函数太杂乱
{
GPIO_InitTypeDef GPIO_InitStrue;//定义一个含初始化参数的结构体
USART_InitTypeDef USART_InitStrue;//定义一个含有初始化该串口所需要参数的结构体
NVIC_InitTypeDef NVIC_InitStrue;//定义一含有设置中断的参数的指针
/*结构体的定义一定要放在最前面,各区域理清后要把结构体的定义挪到最开始*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能串口的时钟
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;//输入输出模式要去技术手册查询
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
/*PA9和PA10初始化完成*/
/*初始化串口,电脑要和下面的参数匹配*/
USART_InitStrue.USART_BaudRate=115200;//只要通信双方波特率一致就可以
USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStrue.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//mode收发模式,在这里设置发送和接收都使能
USART_InitStrue.USART_Parity=USART_Parity_No;
USART_InitStrue.USART_StopBits=USART_StopBits_1;
USART_InitStrue.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&USART_InitStrue);//初始化完成√
USART_Cmd(USART1,ENABLE);//使能串口1
USART_ITConfig (USART1,USART_IT_RXNE,ENABLE);//打开接收中断,接收到数据就会开启中断服务
/*因为使用了中断,要进行中断优先级的设置*/
NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;//
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE ;
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;
NVIC_Init (&NVIC_InitStrue);
}
void USART1_IRQHandler(void)//设置中断服务函数//因为在usart文件中也定义了同名的函数,此时要删除该文件夹
{
if(USART_GetITStatus(USART1,USART_IT_RXNE))
{
u8 ree;
ree = USART_ReceiveData;//接收数据
USART_SendData(USART1,ree );//发送数据
}
}
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//在主函数内第一个调用中断函数
My_USART1_Init();//调用设置的配置函数
while(1);//初始化后保持主函一直数等待中断
}