>_<!功能:PC端發送一個特定的字符:0x0d 0x0a,單片機則返回一句話,如圖:
>_<!知識:
1、復用功能I/O和調試配置(AFIO)
為了優化外設數目,可以把一些復用功能重新映射到其他引腳上。設置復用重映射和調試I/O配置寄存器(AFIO_MAPR)(參見0節)實現引腳的重新映射。這時,復用功能不再映射到它們的原始分配上。
2、嵌套向量中斷控制器(NVIC)
- l 43 個可屏蔽中斷通道(不包含16 個Cortex-M3 的中斷線);
- l 16 個可編程的優先等級;
- l 低延遲的異常和中斷處理;
- l 電源管理控制;
- l 系統控制寄存器的實現;
- l 嵌套向量中斷控制器(NVIC)和處理器核的接口緊密相連,可以實現低延遲的中斷處理和有效處理地處理晚到的中斷。
PS:
a、SysTick:系統嘀嗒校准值固定到9000,當系統嘀嗒時鍾設定為9兆赫,產生1ms時基。
b、中斷和異常向量 :【中斷向量表】
3、USART通用同步異步收發器(USART)
- 它支持同步單向通信和半雙工單線通信
- 任何USART雙向通信至少需要兩個腳:接收數據輸入(RX)和發送數據輸出(TX)。
a、RX:接收數據串行輸。通過過采樣技術來區別數據和噪音,從而恢復數據。
b、TX:發送數據輸出。當發送器被禁止時,輸出引腳恢復到它的I/O 端口配置。當發送器被激活,並且沒東西發送時,TX 引腳處於高電平。
>_<!程序:
a、USART設置,這個要看固件庫!首先用結構體把參數配置好,然后調用初始化函數;接着使能接收中斷和發送緩沖中斷;最后使能USART1。
1 void USART_Config(USART_TypeDef* USARTx){ 2 USART_InitStructure.USART_BaudRate = 19200; //速率19200bps 3 USART_InitStructure.USART_WordLength = USART_WordLength_8b; //數據位8位 4 USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位1位 5 USART_InitStructure.USART_Parity = USART_Parity_No; //無校驗位 6 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //無硬件流控 7 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發模式 8 /* Configure USART1 */ 9 USART_Init(USARTx, &USART_InitStructure); //配置串口參數函數 10 /* Enable USART1 Receive and Transmit interrupts */ 11 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //使能接收中斷 12 USART_ITConfig(USART1, USART_IT_TXE, ENABLE); //使能發送緩沖空中斷 13 /* Enable the USART1 */ 14 USART_Cmd(USART1, ENABLE); 15 }
b、配置系統時鍾72MHz+外設時鍾使能。注意這里有復用,所以要使能復用時鍾。
1 void RCC_Configuration(void){ 2 SystemInit(); 3 RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 |RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_AFIO , ENABLE); 4 }
c、 LED的GPIO口配置和復用的A9,A10用於數據收發
1 void GPIO_Configuration(void){ 2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1控制--PB5 3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出 4 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 5 GPIO_Init(GPIOB, &GPIO_InitStructure); 6 7 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //USART1 TX 8 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復用推挽輸出 9 GPIO_Init(GPIOA, &GPIO_InitStructure); //A端口 10 11 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //USART1 RX 12 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //復用開漏輸入 13 GPIO_Init(GPIOA, &GPIO_InitStructure); //A端口 14 }
d、中斷向量初始化,看固件庫!
1 void NVIC_Configuration(void){ 2 /* 結構聲明*/ 3 NVIC_InitTypeDef NVIC_InitStructure; 4 5 /* Configure the NVIC Preemption Priority Bits */ 6 /* Configure one bit for preemption priority */ 7 /* 優先級組 說明了搶占優先級所用的位數,和子優先級所用的位數 在這里是1, 7 */ 8 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); 9 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //設置串口1中斷 10 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //搶占優先級 0 11 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子優先級為0 12 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能 13 NVIC_Init(&NVIC_InitStructure); 14 }
e、Main函數:rec_f為有效幀標志位
1 int main(void){ 2 uint8_t a=0;//LED高低電壓控制 3 RCC_Configuration(); //系統時鍾設置 4 NVIC_Configuration(); //中斷源配置 5 GPIO_Configuration(); //端口初始化 6 USART_Config(USART1); //串口1初始化 7 8 while (1){ 9 if(rec_f==1){ //判斷是否收到一幀有效數據 10 rec_f=0; 11 for(i=0;i<sizeof(TxBuffer1);i++)//發送字符串 12 { 13 USART_SendChar(USART1,TxBuffer1[i]); 14 Delay(0x0000ff00); 15 } 16 if(a==0){GPIO_SetBits(GPIOB, GPIO_Pin_5);a=1;} //LED1 明暗閃爍 17 else{GPIO_ResetBits(GPIOB, GPIO_Pin_5);a=0;} 18 } 19 } 20 }
這里發送函數封裝為:
1 void USART_SendChar(USART_TypeDef* USARTx,uint8_t data){ 2 USART_SendData(USARTx,data); 3 while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET); 4 }
接收函數在中斷函數中,當上位機發送數據給單片機時,單片機將進入該中斷服務程序,進行數據接收,這里上位機發送的數據必須以0x0d和0x0a結尾,如果不是以這兩個結尾說明不是有效幀,則不處理:
1 void USART1_IRQHandler(void) //串口1 中斷服務程序 2 { 3 unsigned int i; 4 if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //判斷讀寄存器是否非空 5 { 6 RxBuffer1[RxCounter1++] = USART_ReceiveData(USART1); //將讀寄存器的數據緩存到接收緩沖區里 7 if(RxBuffer1[RxCounter1-2]==0x0d&&RxBuffer1[RxCounter1-1]==0x0a)//判斷結束標志是否是0x0d 0x0a 8 { 9 for(i=0; i< RxCounter1; i++) TxBuffer1[i] = RxBuffer1[i]; //將接收緩沖器的數據轉到發送緩沖區,准備轉發 10 rec_f=1; //接收成功標志 11 TxBuffer1[RxCounter1]=0; //發送緩沖區結束符 12 TxCounter1=RxCounter1; 13 RxCounter1=0; 14 } 15 } 16 if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) //這段是為了避免STM32 USART 第一個字節發不出去的BUG 17 { 18 USART_ITConfig(USART1, USART_IT_TXE, DISABLE); //禁止發緩沖器空中斷, 19 } 20 }