天天看點

stm32序列槽解析1:什麼是序列槽2:資料傳輸3:資源介紹4:傳輸協定介紹

1:什麼是序列槽

UART : Universal Asynchronous Receiver/Transmitter 通用異步收發器

USART : Universal Synchronous Asynchronous Receiver/Transmitter 通用同步/異步收發器

序列槽簡單來說就是一種簡單的資料傳輸協定,其資料的傳輸隻需要兩根線即可

2:資料傳輸

有序列槽及必定有并口,并口是指把一個資料一次性傳輸到其他裝置,速度快,效率高,但其傳輸的距離短,成本高故在遠距離的傳輸中并不常用。

序列槽是指在資料傳輸過程中把資料一位一位的傳輸到其他裝置,其傳輸距離遠,但其傳輸的速率較慢,但是用于大多數裝置。

3:資源介紹

stm32序列槽解析1:什麼是序列槽2:資料傳輸3:資源介紹4:傳輸協定介紹

在f4系列中具有6個序列槽,可以獨立進行收發

4:傳輸協定介紹

1:硬體連接配接方式

将兩個裝置的TX,RD 端口交叉相連即可

Tx: 發送資料線

Rx: 接收資料線

stm32序列槽解析1:什麼是序列槽2:資料傳輸3:資源介紹4:傳輸協定介紹

2:工作模式介紹

全雙工: 兩個裝置可以同時發送和接收

半雙工: 在同一瞬間隻能接受或者發送

彈弓模式: 兩個裝置之間隻能接受或者隻能發送

串行資料: 發送隻一根線,一次隻能發送一bit. 一bit接着一bit發送和接收。

子產品通信: 上位機 下位機

通信一般需要兩個裝置,我們把這兩個裝置,人為叫做上位機, 下位機。

上位機: 把處理性能強的機子,上位機。資料大部分處理都在上位機完成。

下位機: 把資料采集的終端,處理性能單一的機子,下位機。

3:資料傳輸模式

1:異步通信:不要求兩個裝置的時鐘一緻,易于實作但每個字元要附加2·3個位用于校驗位,停止位等等

UART protocol 序列槽協定。

序列槽發送和接收資料是以幀為機關. Frame

1幀(Frame)= 1 start bit(起始位) + 5-9bits資料位 + 0/1bit 校驗位  + stop bits(0.5, 1,1,5,2)

起始位: 一個周期的低電平

資料位: 5-9bits資料位,具體是多少bits,需要雙方協商。并且傳送是先傳送LSB(最低位) … MSB

校驗位:

0 bit :沒有校驗位

1 bit :校驗位. “賴子” X

D0 D1 D2 … Dn X

奇校驗:要保證傳輸的1為奇數

偶校驗:要儲存傳輸的1為偶數

停止位: 高電平

0.5 個停止位。 半個周期的高電平

1 個停止位

1.5 個停止位

2 個停止位

2:同步通信

要建立發送方的時鐘對接收方的時鐘嚴格控制,是資料的傳輸完全同步,是由多個字元組成的字元串為傳輸機關來進行資料傳送

特點:傳輸效率高

4:資料傳輸

1:在序列槽資料的收發中有一個十分重要的值 波特率,這是保證兩個裝置之間能狗正常通信的必不可少的資料

Baudrate(波特率): 傳輸速率。

決定 時間周期。

2:序列槽的實體層标準

實體層标準  the physical layer standards

TTL level UART : TTL電平序列槽

RS-232:

RS-422:

RS-485:

TTL level UART:

邏輯低電平(0) 0V

邏輯高電平(1) 5V/3.3V

RS-232: 适合較長距離傳輸

邏輯低電平(0) +3v~+15V

邏輯高電平(1) -3v~-15v

TTL UART RS-232 RS-422 RS-485

電平 1 3.3V/5V 1 -5V ~ -15V +/- 2v +/- 1.5v

0 0V 0 5V ~ +15V

信号 單端信号   單端信号  差分信号   差分信号

傳輸長度 < 2m <15m <1200m <1200m

不同标準的序列槽,引腳也不一樣。TX/Rx是一定存在的。

TTL

RX

TX

GND

VCC

代碼講解

在stm32f4序列槽配置時我們不光要配置其對應的I/O口位複用模式,還需要将其與序列槽連接配接起來,然後配置序列槽傳輸的相關參數

typedef struct
{
  uint32_t USART_BaudRate;          //波特率設定,寄存器BRR

  uint16_t USART_WordLength;         //字長,CR1寄存器 M位

  uint16_t USART_StopBits;            //停止位 ,CR2寄存器 STOP位

  uint16_t USART_Parity;              //校驗控制位,CR1寄存器 PCE,PS位
 
  uint16_t USART_Mode;   //模式選擇,CR1寄存器 TE,RE(收資料使能,Receive Enable)位

  uint16_t USART_HardwareFlowControl;//硬體流選擇,CR3寄存器 CTSE,RTSE位
} USART_InitTypeDef;
           

這個是序列槽配置時相對應的結構體

STM32F4xx序列槽代碼流程

(1) GPIO口配置

序列槽的TX/RX 引腳是由GPIO口來複用的。

a. 使能GPIO分組的時鐘與序列槽分組的時鐘

RCC_AHB1PeriphClockCmd

b. 配置GPIO口的功能 GPIO_Init

c. 選擇具體的複用功能

GPIO_PinAFConfig

(2) usart配置

a:配置序列槽傳輸時的相關配置如波特率,資料位等

b. USART_Init

3) 中斷的配置

USART_ITConfig <- 配置串品的中斷

在STM32中一個USART隻對應一個中斷通道,但是引起序列槽中斷的

事件有很多,比如:

TXE -> 發送寄存器為空,可以引起序列槽中斷

TC -> 發送完成,可以引起序列槽中斷

RXNE -> 接收寄存器不為空,可以引起序列槽中斷

USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);
 	USART_ITConfig就是用來把一個序列槽的XX事件,配置成是否引起序列槽中斷的 		
 	在序列槽中斷函數裡面,就需要判斷是哪個序列槽事件,引起了中斷!!! 		
 	NVIC_Init()
           

(4) 使能序列槽

USART_Cmd

//序列槽中斷
USART1_IRQHanlder()
 	{
 		if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
 		{
 			//有資料可讀啦
 			
 			data = USART_ReceiveData(USART1);  //讀取接收到的資料
 		}
 		//清除USART1的中斷标志
 		USART_GetITStatus
 	}
 USART_GetITStatus用來擷取序列槽的xx事件标志位
           

發送資料

USART_SendData(USART1, 0x55);
 while (USART_GetFlagStatus(USRAT1, USART_FLAG_TXE)  == RESET); //等待發送結束 
           

代碼彙總

#include"stm32f4xx.h"
#include"sys.h"
#include<stdio.h>
static GPIO_InitTypeDef 		GPIO_InitStructure;
static NVIC_InitTypeDef 		NVIC_InitStructure;
static USART_InitTypeDef 		USART_InitStructure;
//标準延時函數
void delay_ms(uint32_t n)
{
	while(n--)
	{
		SysTick->CTRL = 0; 				// Disable SysTick,關閉系統定時器
		SysTick->LOAD = (168000)-1; 	// 配置計數值(168000)-1 ~ 0
		SysTick->VAL  = 0; 		// Clear current value as well as count flag
		SysTick->CTRL = 5; 		// Enable SysTick timer with processor clock
		while ((SysTick->CTRL & 0x10000)==0);// Wait until count flag is set
	}
	
	SysTick->CTRL = 0; 		// Disable SysTick	

}
void usart1_init(uint32_t baud)
{
	//端口A硬體是能
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	//序列槽硬體是能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF ;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	//PF9應交連接配接到序列槽
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
	//配置序列槽
	USART_InitStructure.USART_BaudRate = baud;//波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//資料為
    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);
	//配置中斷觸發方式
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	USART_ClearITPendingBit(USART1,USART_IT_RXNE);	
	//配置終端優先級
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	//使能序列槽工作
	USART_Cmd(USART1, ENABLE);
}

struct __FILE{int handle;};
FILE __stdout;
FILE __stdin;

int fputc(int ch,FILE *f)
{
	USART_SendData(USART1,ch);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
	return ch;
}
//printf函數重定向,可以用printf發送資料
int fgetc(FILE *f)
{
		/* 等待序列槽輸入資料 */
		while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

		return (int)USART_ReceiveData(USART1);
}
int main(void)
{
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOF,&GPIO_InitStructure);
	PFout(9)=1;
	usart1_init(115200);
	printf("sdfrr\r\n");
	while(1)
	{
	}
	
}

void USART1_IRQHandler(void)
{
	uint8_t temp;
	//判斷标志位i
	if(USART_GetFlagStatus(USART1,USART_IT_RXNE)==SET)
	{
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);
		temp=USART_ReceiveData(USART1);
		USART_SendData(USART1,'G');
		while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
		
	}
		
		
}