1.串口知識
串口的應(yīng)用就是芯片給電腦發(fā)數(shù)據(jù),電腦下載程序到芯片上,芯片把芯片存儲器中的數(shù)據(jù)發(fā)回電腦,比如當(dāng)你測量角度或者速度時,芯片測量好后,你要看到,必須讓芯片把數(shù)據(jù)發(fā)回電腦的串口,大致就是這樣。
對于STM32中容量的芯片有3個串口,我們一般使用串口1,說到串口,那么芯片怎么通過串口發(fā)送數(shù)據(jù)到電腦上的,當(dāng)然是通過引腳的端口,如果芯片串口的輸出引腳和外部的RX和TX已經(jīng)集成,那么廠家已經(jīng)把STM32的端口連接到RX和TX上了,把串口看成外部設(shè)備,簡稱外設(shè),廠家已經(jīng)把串口輸出端口內(nèi)部連接到RX和TX上,所以我們不用手動連接,如果沒有,你還需要用杜邦線連接。
如果你還想知道內(nèi)部的硬件情況的話,下圖就是:
我們一般使用USART1串口,所以看表47即可,USART1_REMAP是端口重映像的控制端口,就是端口復(fù)用,在我的STM32上沒有重映像,如果有的話,就應(yīng)該打開復(fù)用時鐘,之后,本文就不講解了。
我們使用PA9和PA10端口,作為TX和RX。
對于PA9和PA10的配置,如下圖:
由表21知,PA9應(yīng)該配置為推挽復(fù)用輸出,PA10應(yīng)該配置為浮空輸入或者上拉輸入。
講了這么多,其實(shí)就是為了說明為什么USART1要進(jìn)行PA9應(yīng)該配置為推挽復(fù)用輸出,PA10應(yīng)該配置為浮空輸入或者上拉輸入這樣的配置,不同的STM型號有可能配置口不太一樣,讀者了解后,查閱相關(guān)資料文檔,應(yīng)該可以找到類似的東西。
2.串口程序編寫的大致步驟
最好在USART.c中加入關(guān)于printf重定義,測試程序會方便很多。
0)printf的重定義
1)變量定義
2)時鐘配置
3)GPIO口的配置
4)USART的配置
5)中斷NVIC配置
6)USART中斷函數(shù)的配置
3.例程
本例程功能:
電腦發(fā)數(shù)據(jù)給串口也就是芯片,芯片回復(fù)收到了;
//加入以下代碼,支持printf函數(shù),而不需要選擇use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//標(biāo)準(zhǔn)庫需要的支持函數(shù)
struct __FILE
{
int handle;
};
FILE __stdout;
//定義_sys_exit()以避免使用半主機(jī)模式
_sys_exit(int x)
{
x = x;
}
//重定義fputc函數(shù)
int fputc(int ch, FILE *f)
{
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
USART_SendData(USART1,(uint8_t)ch);
return ch;
}
#endif
////UASRT1初始化
void uart_init(u32 bound){
//變量定義
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中斷向量組
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA時鐘
//USART1_TX PA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
//USART1_RX PA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10
USART_DeInit(USART1); //復(fù)位串口1
USART_InitStructure.USART_BaudRate = bound;//一般設(shè)置為9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長為8位數(shù)據(jù)格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//無奇偶校驗位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬件數(shù)據(jù)流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發(fā)模式
USART_Init(USART1, &USART_InitStructure); //初始化串口
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//搶占優(yōu)先級3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子優(yōu)先級3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)指定的參數(shù)初始化VIC寄存器
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開啟中斷
USART_Cmd(USART1, ENABLE); //使能串口
}
void USART1_IRQHandler(void){
u8 data_recv;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) // { USART_ClearFlag(USART1,USART_FLAG_RXNE); // 必須清除標(biāo)志 USART_ClearITPendingBit(USART1,USART_IT_RXNE); //
data_recv = USART_ReceiveData(USART1);
//接受的數(shù)據(jù)為data_recv
printf("收到了n");
}
}