工程可見(jiàn)GitHub
從數(shù)據(jù)手冊(cè)可以知道STM32F103RBT6
具有三個(gè)串口
串口引腳及總線對(duì)應(yīng)關(guān)系如下表所示:
串口 USART1 USART2 USART3 管腳(TX/RX) PA9/PA10 PA2/PA3 PB10/PB11 所在總線 APB2 APB1 APB1
三個(gè)串口都是一樣的,但是較硬件電路操作而言,USART1和USART3都接有其他外設(shè),若想通信需要拔掉跳線帽,接入U(xiǎn)SB2TTL。而USART2通過(guò)USB轉(zhuǎn)串口芯片,可直接用一根集下載與通信于一身的USB線進(jìn)行操作了,方便不少。所以本篇博客就只拿USART2來(lái)說(shuō)了,其他兩個(gè)一個(gè)的道理,真有用到修改起來(lái)也不麻煩。
一、主要代碼
main.c
/*******************************************************************************
* 文件名:main.c
* 描 述:
* 作 者:CLAY
* 版本號(hào):v1.0.0
* 日 期: 2019年1月25日
* 備 注:串口發(fā)送20字符以內(nèi)的信息顯示到LCD,并回顯到串口助手
*
*******************************************************************************
*/
#include "stm32f10x.h"
#include "led.h"
#include "key.h"
#include "timer.h"
#include "beep.h"
#include "lcd.h"
#include "stdio.h"
#include "usart.h"
int main(void)
{
u8 i;
u8 str[25];
u8 temp = 30;
float AO = 3.845;
STM3210B_LCD_Init();
LCD_Clear(Blue);
LEDInit();
KeyInit();
BeepInit();
TIM2Init(2000, 72);//定時(shí)2ms
USART2Init(9600);
LCD_DisplayStringLine(Line1,(u8*) "qwertyuioplkjhgfdsazxcvb");
sprintf((char*)str,"temp=%d A0=%.1f ",temp, AO);
LCD_DisplayStringLine(Line2,str);
while(1)
{
KeyDriver();
if(RxdOverFlag)
{
RxdOverFlag = 0;
LCD_ClearLine(Line5);
LCD_DisplayStringLine(Line5, RxdBuf);
USART2_SendByte(RxdBuf);
for(i=0; i<50; i++) RxdBuf[i] = 0;//清空串口接收緩沖區(qū)
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//開(kāi)啟串口接收中斷,處理下一幀數(shù)據(jù)
}
}
}
void KeyAction(int code)
{
if(code == 1)//按下B1,切換燈狀態(tài),蜂鳴器鳴叫0.1s
{
GPIOC->ODR ^= (1<<8);//PC8不斷取反
GPIOD->ODR |= (1<<2);//PD2置1,使能573鎖存器
GPIOD->ODR &= ~(1<<2);//PD2清0,關(guān)閉573鎖存器
Beep(100);
}
else if(code == 2)
{
Beep(-1);
}
else if(code == 3)
{
Beep(0);
}
}
usart.c
/*******************************************************************************
* 文件名:usart.c
* 描 述:
* 作 者:CLAY
* 版本號(hào):v1.0.0
* 日 期: 2019年1月25日
* 備 注:簡(jiǎn)單的串口通信,發(fā)送采用主函數(shù)查詢的方式,接收從采用中斷方式
* 接收緩沖區(qū)考慮到一般要顯示到顯示屏的緣故,所以限制了個(gè)數(shù)20個(gè)
*******************************************************************************
*/
#include "usart.h"
u8 RxdBuf[50];//接收緩沖區(qū)
u8 RxdOverFlag = 0;//接收完成標(biāo)志
u8 RxdCnt = 0;//接收變量計(jì)數(shù)
void USART2_IOInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//PA口時(shí)鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//PA2 - TXD
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//復(fù)用推挽輸出
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3 - RXD
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void NVIC_USART2Enable(void)
{
NVIC_InitTypeDef NVIC_initstructure;
NVIC_initstructure.NVIC_IRQChannel = USART2_IRQn; //選擇TIM2中斷通道
NVIC_initstructure.NVIC_IRQChannelCmd = ENABLE; //使能中斷通道
NVIC_initstructure.NVIC_IRQChannelPreemptionPriority = 0; //設(shè)定搶占優(yōu)先級(jí)為0
NVIC_initstructure.NVIC_IRQChannelSubPriority = 0; //設(shè)定響應(yīng)優(yōu)先級(jí)為0
NVIC_Init(&NVIC_initstructure);
}
void USART2Init(u32 baud)
{
USART_InitTypeDef USART_InitStructure;
USART2_IOInit();
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
USART_InitStructure.USART_BaudRate = baud; //波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8位數(shù)據(jù)位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //1位停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //無(wú)校驗(yàn)位
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART2,&USART_InitStructure); //初始化USART2
NVIC_USART2Enable();//設(shè)置中斷優(yōu)先級(jí)
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//開(kāi)啟串口接收中斷
USART_Cmd(USART2,ENABLE);//使能USART2
}
void USART2_SendByte(u8 *str)
{
u8 index = 0;
while(str[index] != 0)
{
USART_SendData(USART2, str[index]);
while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == 0);//=1表示發(fā)送完成
index++;
}
}
void USART2_RecByte(void)
{
u8 tmp;
tmp = USART_ReceiveData(USART2);
if(tmp != '\n')//結(jié)尾標(biāo)志符號(hào)'\n'并且一次發(fā)送的數(shù)據(jù)不能超過(guò)20(液晶一行顯示20個(gè))
{
RxdBuf[RxdCnt++] = tmp;
if(RxdCnt >= 20)
RxdCnt = 0;
}
else
{
RxdCnt = 0;
RxdOverFlag = 1;
USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);//關(guān)閉接收中斷,等待處理完畢再打開(kāi)
}
}
usart.h
#ifndef _USART_H
#define _USART_H
#include "stm32f10x.h"
void USART2Init(u32 baud);
void USART2_SendByte(u8 *str);
void USART2_RecByte(void);
extern u8 RxdBuf[50];
extern u8 RxdOverFlag;
extern u8 RxdCnt;
#endif
stm32f10x_it.c
...
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2,USART_IT_RXNE) == SET)
{
USART_ClearITPendingBit(USART2,USART_IT_RXNE);
USART2_RecByte();
}
}
...
二、程序解讀
1、關(guān)于USART串口通信此處僅僅是最簡(jiǎn)單的一種測(cè)試,在實(shí)際中并不實(shí)用,之前也寫過(guò)好多實(shí)用的關(guān)于幀模式的,可以去翻翻看。
2、接收采用中斷方式,發(fā)送采用查詢方式
3、之前一篇介紹STM32中斷的文章,此篇稍后再做改進(jìn)。
三、實(shí)驗(yàn)截圖
在這里插入圖片描述
在這里插入圖片描述