今日實驗:實現STM32F407開發板與PC端的串口通信
兩臺計算機進行通信時,最少可以只要三根線,分別為RXD、TXD、GND ;單片機也是一個微型計算機。
前期知識
關于TTL電平
TTL是Transistor-Transistor Logic,即晶體管-晶體管邏輯的簡稱,它是計算機處理器控制的設備內部各部分之間通信的標準技術。TTL電平信號應用廣泛,是因為其數據表示采用二進制規定,+5V等價于邏輯”1”,0V等價于邏輯”0”。
數字電路中,由TTL電子元器件組成電路的電平是個電壓范圍,規定:
輸出高電平>=2.4V,輸出低電平<=0.4V;
輸入高電平>=2.0V,輸入低電平<=0.8V。
關于RS232電平
RS232電平是串口的一個標準;在TXD和RXD數據線上:
邏輯1為-3~-15V的電壓
邏輯0為3~15V的電壓
為什么需要CH340?
CH340是一個電平轉換芯片,我們都知道,計算機識別的是TTL電平,TTL電平在實際中不適合遠距離傳輸;所以我們將其轉換為RS232電平,以適應遠距離傳輸
上面補充了一些理論知識;接下來采用ST公司提供的官方固件庫編寫代碼
//打開文件stm32f4xx_usart.c ,發現它在開頭已經寫好了一堆注釋告訴你如何使用它的庫文件進行開發
//那么我們先分析一下步驟,如何寫出可以進行串口通信的代碼,本例中采用USART1
===============================================================================
##### How to use this driver #####
===============================================================================
[..]
(#) Enable peripheral clock using the following functions
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USARTx, ENABLE) for USART1 and USART6
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USARTx, ENABLE) for USART2, USART3,
UART4 or UART5.
//這第一步便是告訴我們首先要使能外設時鐘,采用RCC_APB2PeriphClockCmd(RCC_APB2Periph_USARTx, ENABLE)
// 這句話可以使能USART1 和 USART6 這兩個外設的時鐘,那我們用USART1就好了
(#) According to the USART mode, enable the GPIO clocks using
RCC_AHB1PeriphClockCmd() function. (The I/O can be TX, RX, CTS,
or/and SCLK).
//第二步,告訴我們使用函數RCC_AHB1PeriphClockCmd()打開相應的GPIO時鐘
(#) Peripheral's alternate function:
(++) Connect the pin to the desired peripherals' Alternate
Function (AF) using GPIO_PinAFConfig() function
(++) Configure the desired pin in alternate function by:
GPIO_InitStruct->GPIO_Mode = GPIO_Mode_AF
(++) Select the type, pull-up/pull-down and output speed via
GPIO_PuPd, GPIO_OType and GPIO_Speed members
(++) Call GPIO_Init() function
//第三步,使用函數GPIO_PinAFConfig()配置相應的GPIO端口復用模式,并調用函數GPIO_Init()進行GPIO初始化
(#) Program the Baud Rate, Word Length , Stop Bit, Parity, Hardware
flow control and Mode(Receiver/Transmitter) using the USART_Init()
function.
//第四步,使用函數USART_Init()配置波特率,數據位,停止位,校驗位,控制流
(#) For synchronous mode, enable the clock and program the polarity,
phase and last bit using the USART_ClockInit() function.
//這一步是采用USART_ClockInit()函數配置同步模式的,因為我們在使用串口通信時沒有用到同步模式,所以不配置
(#) Enable the NVIC and the corresponding interrupt using the function
USART_ITConfig() if you need to use interrupt mode.
//這里是告訴我們要配置中斷向量(NVIC_Init),并使用USART_ITConfig()函數開啟接收中斷
(#) When using the DMA mode
(++) Configure the DMA using DMA_Init() function
(++) Active the needed channel Request using USART_DMACmd() function
//這個DMA模式我們沒用到
(#) Enable the USART using the USART_Cmd() function.
//這個是使能串口,必須的
(#) Enable the DMA using the DMA_Cmd() function, when using DMA mode.
//使能DMA,這里沒用上
-@- Refer to Multi-Processor, LIN, half-duplex, Smartcard, IrDA sub-sections
for more details
[..]
In order to reach higher communication baudrates, it is possible to
enable the oversampling by 8 mode using the function USART_OverSampling8Cmd().
This function should be called after enabling the USART clock (RCC_APBxPeriphClockCmd())
and before calling the function USART_Init().
@endverbatim
******************************************************************************
好了,分析了一下驅動工程師給我們的提示(因為他既然把這個做出來,就肯定要告訴別人怎么用啦),接下來我們使用工程師寫好的固件庫來編寫代碼;噢,還有一點,得看看原理圖我們具體用到哪些引腳
可以看到,PA9對應著USART1的發送端,PA10對應著USART1的接收端;因此在配置相關GPIO時,我們就要把PA9和PA10配置為端口復用模式
根據上面的分析步驟,我們來編寫一下USART1的初始化代碼
/*
*功 能:USART1初始化
*參 數:BaudRate 傳入的波特率值
*返回值:無
*/
void UART1_Init(uint32_t BaudRate)
{
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
//1、開啟USART11時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//2、開啟 GPIOA 時鐘
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA ,ENABLE);
//3、將 PA9 PA10 復用為 串口1 的特殊功能引腳
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; //復用功能
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽輸出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10; //選擇引腳PA9 PA10
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //帶上拉輸出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //輸出速率50MHz
GPIO_Init(GPIOA, &GPIO_InitStruct); //初始化GPIO
//4、配置串口的模式
USART_InitStruct.USART_BaudRate = BaudRate; //波特率
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//關閉硬件流控,因為目前只用到三根線,收(RXT),發(TXD),地(GND);不同于九頭串口線有9根線
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收發模式兼具
USART_InitStruct.USART_Parity = USART_Parity_No; //無檢驗位
USART_InitStruct.USART_StopBits = USART_StopBits_1; //1位停止位
USART_InitStruct.USART_WordLength = USART_WordLength_8b; //8位數據位
USART_Init(USART1 ,&USART_InitStruct);
//5、開啟 接收 中斷
USART_ITConfig(USART1 , USART_IT_RXNE ,ENABLE);
//6、使能 NVIC ,使用到中斷,一定要配置NVIC
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStruct);
//7、使能USART1
USART_Cmd(USART1 ,ENABLE);
}
寫好USART1的初始化函數,接下來要寫它的中斷服務函數
uint32_t r_value;
void USART1_IRQHandler(void)
{
//檢測數據接收標志位
if((USART_GetFlagStatus(USART1, USART_IT_RXNE)) != RESET)
{
//清除標志位
USART_ClearFlag(USART1, USART_IT_RXNE);
r_value = USART_ReceiveData(USART1); //接收數據,開發板接收來自電腦串口調試終端發送的數據
if(r_value == 'd') //如果接收到字符d ,可執行相應操作,這里做個小測試,通過串口傳輸控制LED的亮滅
{
//LED0亮
GPIO_ResetBits(GPIOF, GPIO_Pin_9);
}else{
GPIO_SetBits(GPIOF, GPIO_Pin_9);
}
USART_SendData(USART1, r_value); //發送數據 ,開發板向電腦發送數據 ;將顯示在串口調試終端上
}
}
#include "stm32f4xx.h"
#include "led.h"
#include "uart.h"
//主程序代碼
int main(void)
{
LED_Init(); //LED初始化
USART1_Init(115200); //串口初始化
while(1)
{
//空循環,等待串口中斷的發生
}
}
以上代碼便實現了兩個STM332與電腦之間的串口通信;
不過我們也發現個問題,使用官方提供的庫函數,我們就一次只能發送或接收一個字符,那如果我想一次發送一字符串咋辦呢?那就自己再另外寫個函數唄
/*
*功 能:發送一串字符串
*參 數:傳入字符串首地址
*返回值:無
*/
void UART1_SendString(const char *str)
{
uint8_t i = 0;
//判斷是否達到字符串末尾
while( *(str+i) != ' 主站蜘蛛池模板: 娱乐| 柘荣县| 南汇区| 晋城| 陕西省| 渭源县| 防城港市| 大庆市| 盐源县| 余庆县| 城市| 含山县| 新兴县| 子洲县| 邯郸市| 凤台县| 沂南县| 海口市| 恩平市| 那曲县| 应用必备| 曲沃县| 凤城市| 永吉县| 唐海县| 二连浩特市| 富源县| 扎囊县| 宾阳县| 会昌县| 彭泽县| 宝山区| 左权县| 图木舒克市| 乐东| 库车县| 武定县| 琼海市| 肇源县| 措勤县| 繁昌县|