STM32F429之UART使用

#if 1
/// 重定向c庫函數printf到USART1
int fputc(int ch, FILE *f)
{
        /* 發送一個字節數據到USART1 */
        USART_SendData(USART1, (uint8_t) ch);
        
        /* 等待發送完毿*/
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);        
    
        return (ch);
}函數

/// 重定向c庫函數scanf到USART1
int fgetc(FILE *f)
{
        /* 等待串口1輸入數據 */
        while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);ui

        return (int)USART_ReceiveData(USART1);
}
#endif
/*********************************************END OF FILE**********************/
 spa

USART 只需兩根信號線便可完成雙向通訊,對硬件要求低,使得不少模塊都預留USART 接口來實現與其餘模塊或者控制器進行數據傳輸,好比 GSM 模塊, WIFI 模塊、藍牙模塊調試

  APB2(最高 90MHz)                                     APB1(最高 45MHz)
  USART1 USART6 USART2 USART3 UART4 UART5 UART7 UART8
TX PA9/PB6 PC6/PG14 PA2/PD5 PB10/PD8
/PC10
PA0/PC10 PC12 PF7/PE8 PE1
RX PA10/PB7 PC7/PG9 PA3/PD6 PB11/PD9
/PC11
PA1/PC11 PD2 PF6/PE7 PE0
SCLK PA8 PG7/PC8 PA4/PD7 PB12/PD10
/PC12
       
nCTS PA11 PG13/PG15 PA0/PD3 PB13/PD11        
nRTS PA12 PG8/PG12 PA1/PD4 PB14/PD12        

串口1收發數據配置code

配合原子的 usmart能夠方便的進行調試,使用usmart能夠經過串口調用函數,能夠傳參數很是方便。blog

void NVIC_Configuration_1(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	/* 配置 NVIC 爲優先級綠1 */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	/* 配置中斷源:按鍵 1 */
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	/* 配置搶佔優先級: 1 */
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
	/* 配置子優先級_1 */
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
	/* 使能中斷通道 */
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

void USART1_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	/* config USART1 clock */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
	
	/* USART1 GPIO config */
	/* Configure USART1 Tx (PA.09) as alternate function push-pull */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);    
	
	/* Configure USART1 Rx (PA.10) as input floating */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	/* USART1 mode config */
	USART_InitStructure.USART_BaudRate = 115200;
	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);
	NVIC_Configuration_1();
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	USART_Cmd(USART1, DISABLE);
	(void)USART1->SR; (void)USART1->DR;
	USART_ClearFlag(USART1, USART_FLAG_TC);
	USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	USART_Cmd(USART1, ENABLE);

}



void USART1_IRQHandler_FUN(void)
{

	u8 data;

	(void)USART1->SR;   //Error clear;
	data =	(u8)(USART1->DR & (u16)0x01FF);
	USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	resevice_buf(data);//
	get_buf_usart1[get_usart1_i] = data;
	USART_SendData(USART1, data);	
	get_usart1_i++;
	if(get_buf_usart1[0] != 0xFF)
	{
		get_usart1_i=0;
	}
		
	if(get_usart1_i==4)
	{	
		AnalizingBuf2();
		get_usart1_i = 0;
		gRxHostBufferFlush(4,get_buf_usart1);
	}
	
}
/// 重定向c庫函數printf到USART1
int fputc(int ch, FILE *f)
{
		/* 發送一個字節數據到USART1 */
		USART_SendData(USART1, (uint8_t) ch);
		
		/* 等待發送完毿*/
		while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);		
	
		return (ch);
}

/// 重定向c庫函數scanf到USART1
int fgetc(FILE *f)
{
		/* 等待串口1輸入數據 */
		while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

		return (int)USART_ReceiveData(USART1);
}


 

使用USART1進行串口調試,打印信息到電腦接口

程序是如何找到中斷服務程序呢?在啓動文件startup_stm32f10x_md.s中有這樣一段代碼,彙編DCD USART1_IRQHandler 事件

 

stm32串口調試是一個很好的方法ip

通常有4個上的串口,能夠將printf函數重定向到一個UART。這樣就能夠用printf函數將單片機的數據打印到PC上的超級終端或串口調試助手。字符串

能夠經過串口發送一些參數方便調試,能夠用一個協議易於操做

 

//定義一個協議,關於數據收發的
//第一位:判斷數據是否正確
//第二位:判斷數據是否正確
//第三位:存放參數多少
//第四位:參數[1]
//第五位:參數[2]
//第n位:參數[n]
/*
Buffur_Full接受完畢標誌位,意思能夠解析程序了
*/
 
char get_From_PC[64];
bool Buffur_Full = FALSE;//定義成全局變量
char buf[64];//定義成全局變量
int buf_conut =0
 
void DEBUG_USART_IRQHandler(void)
{
    uint8_t ucTemp;
 
    if (USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET) {
        buf[buf_conut++] = USART_ReceiveData( USART1 );
        PacketCheck();
    }
}
void BufferFlush(u32 BufferSize){
    for(u32 counter=0; counter<BufferSize; counter++) buf[counter] = 0;
}
void PacketCheck(void)
{
    int para_length = 0;
    //Header Check
    if(buf[0]!=0xff){ BufferFlush(buf_conut); buf_conut=0; return; }
    else if(buf_conut==1) return;
        if(buf[1]!=0xff){ BufferFlush(buf_conut); buf_conut=0; return; }
        else if(buf_conut==2) return;
    
    if(buf_conut>2)
    {    
        para_length = buf[2];
        if(buf_conut - 2> para_length)
        {
            for(int i= 0;i<para_length ;i++)
            {
                get_From_PC[i] = buf[i+3];
            }
        }
        if(buf_conut == para_length +2)
        {
            Buffur_Full = TURE;
            gRxHostBufferFlush(buf_conut);
            buf_conut = 0;
        }
    }
 
}
 

 

 

/*
嵌套向量中斷控制器 NVIC 配置
中斷控制器 NVIC 配置
*/
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 嵌套向量中斷控制器組選擇 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 配置 USART 爲中斷源 */
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
/* 搶斷優先級爲 1 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/* 子優先級爲 1 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* 使能中斷 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* 初始化配置 NVIC */
NVIC_Init(&NVIC_InitStructure);
}
 

工做模式配置
//USART 初始化配置
void Debug_USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
/* 使能 USART GPIO 時鐘 */
RCC_AHB1PeriphClockCmd(DEBUG_USART_RX_GPIO_CLK |
DEBUG_USART_TX_GPIO_CLK,
ENABLE);
/* 使能 USART 時鐘 */
RCC_APB2PeriphClockCmd(DEBUG_USART_CLK, ENABLE);
/* GPIO 初始化 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* 配置 Tx 引腳爲複用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_PIN ;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
/* 配置 Rx 引腳爲複用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_PIN;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
/* 鏈接 PXx 到 USARTx_Tx*/
GPIO_PinAFConfig(DEBUG_USART_RX_GPIO_PORT,
DEBUG_USART_RX_SOURCE,
DEBUG_USART_RX_AF);
/* 鏈接 PXx 到 USARTx__Rx*/
GPIO_PinAFConfig(DEBUG_USART_TX_GPIO_PORT,
DEBUG_USART_TX_SOURCE,
DEBUG_USART_TX_AF);
/* 配置串 DEBUG_USART 模式 */
/* 波特率設置: DEBUG_USART_BAUDRATE */
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
/* 字長(數據位+校驗位): 8 */
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
/* 中止位: 1 箇中止位 */
USART_InitStructure.USART_StopBits = USART_StopBits_1;
/* 校驗位選擇:不使用校驗 */
USART_InitStructure.USART_Parity = USART_Parity_No;
/* 硬件流控制:不使用硬件流 */
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
/* USART 模式控制:同時使能接收和發送 */
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* 完成 USART 初始化配置 */
USART_Init(DEBUG_USART, &USART_InitStructure);
/* 嵌套向量中斷控制器 NVIC 配置 */
NVIC_Configuration();
/* 使能串口接收中斷 */
USART_ITConfig(DEBUG_USART, USART_IT_RXNE, ENABLE
/* 使能串口 */
USART_Cmd(DEBUG_USART, ENABLE);
}
GPIO_PinAFConfig 函數接收三個參數,第一個參數爲 GPIO 端口,好比 GPIOA;第二個參數是指定要複用的引腳號,好比 GPIO_PinSource10;第三個參數是選擇複用外設,好比 GPIO_AF_USART1。該函數最終操做的是 GPIO 複用功能寄存器 GPIO_AFRH 和GPIO_AFRL,分高低兩個。
 

字符發送
/***************** 發送一個字符 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
/* 發送一個字節數據到 USART */
USART_SendData(pUSARTx,ch);
/* 等待發送數據寄存器爲空 */
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
/***************** 發送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
unsigned int k=0;
do {
Usart_SendByte( pUSARTx, *(str + k) );
k++;
} while (*(str + k)!='\0');
/* 等待發送完成 */
while (USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET) {
}
}
Usart_SendByte 函數用來在指定 USART 發送一個 ASCLL 碼值字符,它有兩個形參,第一個爲 USART,第二個爲待發送的字符。它是經過調用庫函數 USART_SendData 來實現的,而且增長了等待發送完成功能。經過使用 USART_GetFlagStatus 函數來獲取 USART事件標誌來實現發送完成功能等待,它接收兩個參數,一個是 USART,一個是事件標誌。這裏咱們循環檢測發送數據寄存器爲空這個標誌,當跳出 while 循環時說明發送數據寄存器爲空這個事實。
Usart_SendString 函數用來發送一個字符串,它實際是調用 Usart_SendByte 函數發送每一個字符,直到遇到空字符才中止發送。最後使用循環檢測發送完成的事件標誌來實現保證數據發送完成後才退出函數
 

USART 中斷服務函數
void DEBUG_USART_IRQHandler(void)
{
uint8_t ucTemp;
if (USART_GetITStatus(DEBUG_USART,USART_IT_RXNE)!=RESET) {
ucTemp = USART_ReceiveData( DEBUG_USART );
USART_SendData(DEBUG_USART,ucTemp);
}
}
 

這段代碼是存放在 stm32f4xx_it.c 文件中的,該文件用來集中存放外設中斷服務函數。當咱們使能了中斷而且中斷髮生時就會執行中斷服務函數。 使能了 USART 接收中斷,當 USART 有接收到數據就會執行DEBUG_USART_IRQHandler 函數。 USART_GetITStatus 函數與 USART_GetFlagStatus 函數相似用來獲取標誌位狀態,但 USART_GetITStatus 函數是專門用來獲取中斷事件標誌的,並返回該標誌位狀態。使用 if 語句來判斷是不是真的產生 USART 數據接收這個中斷事件,若是是真的就使用 USART 數據讀取函數 USART_ReceiveData 讀取數據到指定存儲區。而後再調用 USART 數據發送函數 USART_SendData 把數據又發送給源設備。