找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 2654|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

STM32之串口通信

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:107189 發(fā)表于 2016-3-4 20:13 | 只看該作者 回帖獎(jiǎng)勵(lì) |正序?yàn)g覽 |閱讀模式
實(shí)驗(yàn)?zāi)康模?/div>
實(shí)現(xiàn)利用串口1不停的打印一個(gè)信息到電腦上,同時(shí)接收從串口發(fā)過來的數(shù)據(jù),把發(fā)送過來的數(shù)據(jù)直接送回給電腦。
實(shí)驗(yàn)平臺(tái):
基于STM32F103C8T6的彩屏開發(fā)板
硬件接口:
      
注意:因?yàn)槲业拈_發(fā)板上的串口和LED共用了PA9和PA10,所以在使用USART1時(shí)務(wù)必屏蔽LED,不然兩者會(huì)互相影響而導(dǎo)致實(shí)現(xiàn)現(xiàn)象無法呈現(xiàn)。
相關(guān)寄存器:
1,串口時(shí)鐘使能。串口作為STM32 的一個(gè)外設(shè),其時(shí)鐘由外設(shè)時(shí)鐘使能寄存器控制,這
里我們使用的串口1 是在APB2ENR 寄存器的第14 位。
2,串口復(fù)位。串口1 的復(fù)位是通過配置APB2RSTR 寄存器的第14位來實(shí)現(xiàn)的。。通過向該位寫1來復(fù)位串口1,寫0 結(jié)束復(fù)位。
3,串口波特率設(shè)置。每個(gè)串口都有一個(gè)自己獨(dú)立的波特率寄存器USART_BRR
波特率的計(jì)算,STM32 的串口波特率計(jì)算公式如下:
                       
上式中, 是給串口的時(shí)鐘(PCLK1 用于USART2、3、4、5,PCLK2 用于USART1);USARTDIV是一個(gè)無符號(hào)定點(diǎn)數(shù)。我們只要得到USARTDIV 的值,就可以得到串口波特率寄存器USART1->BRR的值。
4,串口控制。STM32 的每個(gè)串口都有3 個(gè)控制寄存器USART_CR1~3,串口的很多配置
都是通過這3 個(gè)寄存器來設(shè)置的
5,數(shù)據(jù)發(fā)送與接收。STM32 的發(fā)送與接收是通過數(shù)據(jù)寄存器USART_DR 來實(shí)現(xiàn)的,這是
一個(gè)雙寄存器,包含了TDR 和RDR。
6,串口狀態(tài)。串口的狀態(tài)可以通過狀態(tài)寄存器USART_SR 讀取。
(注:詳細(xì)的介紹使用請(qǐng)參考ST公司的數(shù)據(jù)手冊(cè))
程序設(shè)計(jì):
(注:本人的usart.c usart.h delay.cdelay.h sys.c sys.h是引用網(wǎng)上一位網(wǎng)友整理的)
    usart.h
#ifndef __USART_H
#define __USART_H
#include<stm32f10x_lib.h>
#include"stdio.h"   
extern u8USART_RX_BUF[64];    //接收緩沖,最大63個(gè)字節(jié).末字節(jié)為換行符
extern u8USART_RX_STA;        //接收狀態(tài)標(biāo)記   
//如果想串口中斷接收,請(qǐng)不要注釋以下宏定義
#define EN_USART1_RX //使能串口1接收
void uart_init(u32 pclk2,u32 bound);
#endif     
    usart.c
#include "sys.h"
#include "usart.h"
//加入以下代碼,支持printf函數(shù),而不需要選擇useMicroLIB   
#if 1
#pragmaimport(__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((USART1->SR&0X40)==0);//循環(huán)發(fā)送,直到發(fā)送完畢  
  USART1->DR = (u8)ch;     
  return ch;
}
#endif
//end
//////////////////////////////////////////////////////////////////
#ifdefEN_USART1_RX   //如果使能了接收
//串口1中斷服務(wù)程序
//注意,讀取USARTx->SR能避免莫名其妙的錯(cuò)誤   
u8USART_RX_BUF[64];    //接收緩沖,最大64個(gè)字節(jié).
//接收狀態(tài)
//bit7,接收完成標(biāo)志
//bit6,接收到0x0d
//bit5~0,接收到的有效字節(jié)數(shù)目
u8USART_RX_STA=0;      //接收狀態(tài)標(biāo)記   
void USART1_IRQHandler(void)
{
  u8 res;   
if(USART1->SR&(1<<5))//接收到數(shù)據(jù)
{  
     res=USART1->DR;
     if((USART_RX_STA&0x80)==0)//接收未完成
     {
         if(USART_RX_STA&0x40)//接收到了0x0d
         {
             if(res!=0x0a)
                 USART_RX_STA=0;//接收錯(cuò)誤,重新開始
             else
                 USART_RX_STA|=0x80; //接收完成了
         }else //還沒收到0X0D
         {  
             if(res==0x0d)
                 USART_RX_STA|=0x40;
             else
             {
                 USART_RX_BUF[USART_RX_STA&0X3F]=res;
                 USART_RX_STA++;
                 if(USART_RX_STA>63)USART_RX_STA=0;//接收數(shù)據(jù)錯(cuò)誤,重新開始接收   
             }      
         }
     }                                             
  }                                          
}
#endif
//該函數(shù)的重點(diǎn)就是判斷接收是否完成,通過檢測(cè)是否收到0X0D、0X0A 的連續(xù)2 個(gè)字節(jié)//(0X0D 后跟0X0A表示回車鍵)來檢測(cè)是否結(jié)束。當(dāng)檢測(cè)到這個(gè)結(jié)束序列之后,就會(huì)置//位USART_RX_STA的最高為來標(biāo)記已經(jīng)收到了一次數(shù)據(jù)。之后等待外部函數(shù)清空該位//之后才開始第二次接收。所接收的數(shù)據(jù)全部存放在USART_RX_BUF里面,一次接收數(shù)//據(jù)不能超過64個(gè)字節(jié),否則被丟棄。                                   
//初始化IO 串口1
//pclk2:PCLK2時(shí)鐘頻率(Mhz)
//bound:波特率
//CHECK OK
//091209
void uart_init(u32 pclk2,u32 bound)
{     
  float temp;
  u16 mantissa;
  u16fraction;   
temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
mantissa=temp;             //得到整數(shù)部分
  fraction=(temp-mantissa)*16;//得到小數(shù)部分
   mantissa<<=4;
  mantissa+=fraction;
RCC->APB2ENR|=1<<2;  //使能PORTA口時(shí)鐘
RCC->APB2ENR|=1<<14; //使能串口時(shí)鐘
GPIOA->CRH&=0XFFFFF00F;
GPIOA->CRH|=0X000008B0;//IO狀態(tài)設(shè)置
      
RCC->APB2RSTR|=1<<14;  //復(fù)位串口1
RCC->APB2RSTR&=~(1<<14);//停止復(fù)位      
  //波特率設(shè)置
USART1->BRR=mantissa; // 波特率設(shè)置
USART1->CR1|=0X200C; //1位停止,無校驗(yàn)位.
#ifdefEN_USART1_RX        //如果使能了接收
  //使能接收中斷
USART1->CR1|=1<<8;   //PE中斷使能
USART1->CR1|=1<<5;   //接收緩沖區(qū)非空中斷使能      
MY_NVIC_Init(3,3,USART1_IRQChannel,2);//組2,最低優(yōu)先級(jí)
#endif
}
  主函數(shù)
#include<stm32f10x_lib.h>
#include"common.h"   
int main(void)
{        
  u8 t;
  u8 len;
  u16times=0;
  Stm32_Clock_Init(9);//系統(tǒng)時(shí)鐘設(shè)置
  delay_init(72);    //延時(shí)初始化
  uart_init(72,9600);//串口初始化為9600
  while(1)
  {
     if(USART_RX_STA&0x80)
     {                    
         len=USART_RX_STA&0x3f;//得到此次接收到的數(shù)據(jù)長度
         printf("\n您發(fā)送的消息為:\n");
         for(t=0;t<len;t++)
         {
             USART1->DR=USART_RX_BUF[t];
             while((USART1->SR&0X40)==0);//等待發(fā)送結(jié)束
         }
         printf("\n\n");//插入換行
         USART_RX_STA=0;
     }else
     {
         times++;
         if(timesP00==0)
         {
             printf("\n 簡(jiǎn)單的串口實(shí)驗(yàn)\n");
         }
         if(times 0==0)printf("請(qǐng)輸入數(shù)據(jù),以回車鍵結(jié)束\n");
         delay_ms(10);  
     }
}  
}
實(shí)驗(yàn)現(xiàn)象:



分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表