基於stm32f103zet6的串口學習

來源:互聯網
上載者:User

進行串口配置的步驟
一、初始化GPIO,配置GPIO模式
一個結構體
GPIO_InitTypeDef{
GPIOMode_TypeDef  GPIO_Mode
//GPIO模式,輸入,輸出? 
uint16_t  GPIO_Pin
//哪個管腳?
GPIOSpeed_TypeDef  GPIO_Speed
//輸出響應速度?如果為輸入則可以不設定
}
//GPIO_Mode包括以下幾種方式
Enumerator: 枚舉類型
GPIO_Mode_AIN   //類比輸入 
GPIO_Mode_IN_FLOATING   //懸浮輸入
GPIO_Mode_IPD   //下拉輸入
GPIO_Mode_IPU   //上拉輸入
GPIO_Mode_Out_OD   //開漏輸出
GPIO_Mode_Out_PP   //推挽輸出//push pull  直接輸出為高低,當選用開漏的時候需要外接三極體
GPIO_Mode_AF_OD   //複用開漏輸出
GPIO_Mode_AF_PP   //複用推挽輸出
//GPIO_Pin包括以下幾種方式
#define  GPIO_Pin_0   ((uint16_t)0x0001) 
#define  GPIO_Pin_1   ((uint16_t)0x0002) 
#define  GPIO_Pin_10   ((uint16_t)0x0400) 
#define  GPIO_Pin_11   ((uint16_t)0x0800) 
#define  GPIO_Pin_12   ((uint16_t)0x1000) 
#define  GPIO_Pin_13   ((uint16_t)0x2000) 
#define  GPIO_Pin_14   ((uint16_t)0x4000) 
#define  GPIO_Pin_15   ((uint16_t)0x8000) 
#define  GPIO_Pin_2   ((uint16_t)0x0004) 
#define  GPIO_Pin_3   ((uint16_t)0x0008) 
#define  GPIO_Pin_4   ((uint16_t)0x0010) 
#define  GPIO_Pin_5   ((uint16_t)0x0020) 
#define  GPIO_Pin_6   ((uint16_t)0x0040) 
#define  GPIO_Pin_7   ((uint16_t)0x0080) 
#define  GPIO_Pin_8   ((uint16_t)0x0100) 
#define  GPIO_Pin_9   ((uint16_t)0x0200) 
#define  GPIO_Pin_All   ((uint16_t)0xFFFF) 
#define  IS_GET_GPIO_PIN(PIN) //??
#define  IS_GPIO_PIN(PIN)   ((((PIN) & (uint16_t)0x00) == 0x00) && ((PIN) != (uint16_t)0x00)) //???
//GPIO_Speed的模式有以下幾種,同樣是一個枚舉類型
Output Maximum frequency selection. 
Enumerator: 
GPIO_Speed_10MHz   
GPIO_Speed_2MHz   
GPIO_Speed_50MHz   
//TXD為輸出,RXD為浮空輸入
//選用usart1的時候管腳應該是PA9(TXD),PA10(RXD)
//所以不難得出,初始化的時候它的設計語句應該是
//GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_AF_PP
//GPIO_InitStructure.GPIO_Pin  =  GPIO_Pin_9
//PIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

//GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IN_FLOATING
//GPIO_InitStructure.GPIO_Pin  =  GPIO_Pin_10
//PIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
那麼至此為止,我的猜測GPIO初始化完畢,驗證一下!
/* 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);
看來問題不是很大,只是最後需要加上  GPIO_Init(GPIOA, &GPIO_InitStructure);
來指定對哪個GPIO進行初始化!
二、接下來初始化串口
// USART_InitTypeDef USART_InitStructure;
//定義串口初始化結構體
還一個結構體
USART_InitTypeDef{
uint32_t  USART_BaudRate //傳輸速率比率
uint16_t  USART_HardwareFlowControl //硬體流,所謂硬體流待查證
uint16_t  USART_Mode //串口模式,這個比較豐富
uint16_t  USART_Parity //雖然不認識,但是參測應該是同位位元
uint16_t  USART_StopBits //停止位
uint16_t  USART_WordLength //長度
}
1、一個一個進行分析,首先是USART_BaudRate
先來一個計算運算式,這個和arm11的有些類似哈
This member configures the USART communication baud rate. 
The baud rate is computed using the following formula:

IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate)))
//整數部分
FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5
//小數部分
//這裡涉及到另外一個結構體USART_InitStruct,跟蹤下去,發現這是同一個結構體,按就好辦了!直接根據傳輸速率
//就能計算出其整數部分和小數部分,它可以取的數雖然多,但是有誤差大小之分!9600 、11520等為0誤差的!
2、USART_HardwareFlowControl,它的取值可以是這樣
#define  IS_USART_HARDWARE_FLOW_CONTROL(CONTROL) 
#define  USART_HardwareFlowControl_CTS   ((uint16_t)0x0200) 
#define  USART_HardwareFlowControl_None   ((uint16_t)0x0000)
//據介紹應該是不使用硬體流
#define  USART_HardwareFlowControl_RTS   ((uint16_t)0x0100) 
#define  USART_HardwareFlowControl_RTS_CTS   ((uint16_t)0x0300) 
3、USART_Mode,三種
#define  IS_USART_MODE(MODE)   ((((MODE) & (uint16_t)0xFFF3) == 0x00) && ((MODE) != (uint16_t)0x00)) //雙工
#define  USART_Mode_Rx   ((uint16_t)0x0004) 
#define  USART_Mode_Tx   ((uint16_t)0x0008) 
4、USART_Parity有以下幾種取值
#define  IS_USART_PARITY(PARITY) 
#define  USART_Parity_Even   ((uint16_t)0x0400) 
#define  USART_Parity_No   ((uint16_t)0x0000) //無奇偶標誌位
#define  USART_Parity_Odd   ((uint16_t)0x0600) 
5、USART_StopBits、USART_WordLength這兩個很明顯,不解釋了!
分析上面之後基本上能夠確定串口的配置了
//USART_InitStructure.USART_BaudRate = 11520
//USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None
//USART_InitStructure.USART_Mode = IS_USART_MODE(MODE)
//USART_InitStructure.USART_Parity = USART_Parity_No
//USART_InitStructure.USART_StopBits = USART_StopBits_1
//USART_InitStructure.USART_WordLength = USART_WordLength_8b
最後幾句就是我們常說的8N1
下面來驗證一下!
/* 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); 
USART_Cmd(USART1, ENABLE);
/*問題還是有不少啊
1、首先是傳輸速率搞錯應該是115200 不是 11520
2、然後是模式選錯,全雙工系統應該是USART_Mode_Rx | USART_Mode_Tx;
3、串口只是配置了,又沒有初始化
4、還有串口沒有使能
三、第一第二步之後,串口初始化完,下面我們就需要使用到串口了,是否還是像以前的單片機那樣,
如果想要向串口發送資料就直接寫個函數,個BUFF裡面寫資料呢?不,那效率太低了,我們使用到printf函數
系統庫函數調用,下面就需要重新導向!
1、我再arm11的參考書上面瞭解到,所謂重新導向就是指,本來如果調用系統庫的話,那麼printf函數答應的
資訊是顯示到調試器視窗的,但是當我們重新導向後,列印的資訊就是在串口裡面了,同時也能實現到彩屏上
去。
2、調用庫函數必須包含stdio.h函數,現在來跟蹤一下這個printf函數到底有什麼東西
#include <libioP.h>
#include <stdarg.h>
#include <stdio.h>
/* Write formatted output to stdout from the format string FORMAT.  */
/* VARARGS1 */
int __printf (const char *format, ...)
{
  va_list arg;
  int done;

  va_start (arg, format);
  done = vfprintf (stdout, format, arg);
  va_end (arg);

  return done;
}
繼續看

int vsprintf(char *buf, const char *fmt, va_list args)
{
  int len;
  unsigned long num;
  int i, base;
  char *str;
  char *s;

  int flags;            // Flags to number()

  int field_width; // Width of output field
  int precision; // Min. # of digits for integers; max number of chars for from string
  int qualifier; // 'h', 'l', or 'L' for integer fields

  for (str = buf; *fmt; fmt++)
  {
    if (*fmt != '%')
    {
      *str++ = *fmt;
      continue;
    }
 
    // Process flags
    flags = 0;
repeat:
    fmt++; // This also skips first '%'
    switch (*fmt)
    {
      case '-': flags |= LEFT; goto repeat;
      case '+': flags |= PLUS; goto repeat;
      case ' ': flags |= SPACE; goto repeat;
      case '#': flags |= SPECIAL; goto repeat;
      case '0': flags |= ZEROPAD; goto repeat;
    }
 
    // Get field width
    field_width = -1;
    if (is_digit(*fmt))
      field_width = skip_atoi(&fmt);
    else if (*fmt == '*')
    {
      fmt++;
      field_width = va_arg(args, int);
      if (field_width < 0)
      {
field_width = -field_width;
flags |= LEFT;
      }
    }

    // Get the precision
    precision = -1;
    if (*fmt == '.')
    {
      ++fmt;
      if (is_digit(*fmt))
        precision = skip_atoi(&fmt);
      else if (*fmt == '*')
      {
        ++fmt;
        precision = va_arg(args, int);
      }
      if (precision < 0) precision = 0;
    }

    // Get the conversion qualifier
    qualifier = -1;
    if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L')
    {
      qualifier = *fmt;
      fmt++;
    }

    // Default base
    base = 10;

    switch (*fmt)
    {
      case 'c':
if (!(flags & LEFT)) while (--field_width > 0) *str++ = ' ';
*str++ = (unsigned char) va_arg(args, int);
while (--field_width > 0) *str++ = ' ';
continue;

      case 's':
s = va_arg(args, char *);
if (!s)
s = "<NULL>";
len = strnlen(s, precision);
if (!(flags & LEFT)) while (len < field_width--) *str++ = ' ';
for (i = 0; i < len; ++i) *str++ = *s++;
while (len < field_width--) *str++ = ' ';
continue;

      case 'p':
if (field_width == -1)
{
 field_width = 2 * sizeof(void *);
 flags |= ZEROPAD;
}
str = number(str, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags);
continue;

      case 'n':
if (qualifier == 'l')
{
 long *ip = va_arg(args, long *);
 *ip = (str - buf);
}
else
{
 int *ip = va_arg(args, int *);
 *ip = (str - buf);
}
continue;

      case 'A':
flags |= LARGE;

      case 'a':
if (qualifier == 'l')
 str = eaddr(str, va_arg(args, unsigned char *), field_width, precision, flags);
else
 str = iaddr(str, va_arg(args, unsigned char *), field_width, precision, flags);
continue;

      // Integer number formats - set up the flags and "break"
      case 'o':
base = 8;
break;

      case 'X':
flags |= LARGE;

      case 'x':
base = 16;
break;

      case 'd':
      case 'i':
flags |= SIGN;

      case 'u':
break;

      case 'E':
      case 'G':
      case 'e':
      case 'f':
      case 'g':
        str = flt(str, va_arg(args, double), field_width, precision, *fmt, flags | SIGN);
continue;

      default:
if (*fmt != '%') *str++ = '%';
if (*fmt)
 *str++ = *fmt;
else
 --fmt;
continue;
    }

    if (qualifier == 'l')
      num = va_arg(args, unsigned long);
    else if (qualifier == 'h')
    {
      if (flags & SIGN)
num = va_arg(args, short);
      else
num = va_arg(args, unsigned short);
    }
    else if (flags & SIGN)
      num = va_arg(args, int);
    else
      num = va_arg(args, unsigned int);

    str = number(str, num, base, field_width, precision, flags);
  }

  *str = '\0';
  return str - buf;
}
似乎沒有找到我需要的東西,那就算了,這裡算我沒搞懂了,留著這個問題,直接上代碼吧,反正這兩個
函數可以肯定是在scanf和printf裡面調用的
/*
 * 函數名:fputc
 * 描述  :重新導向c庫函數printf到USART1
 * 輸入  :無
 * 輸出  :無
 * 調用  :由printf調用
 */
int fputc(int ch, FILE *f)
{
/* 將Printf內容發往串口 */
  USART_SendData(USART1, (unsigned char) ch);
  while (!(USART1->SR & USART_FLAG_TXE));
 
  return (ch);
}

int fgetc(FILE *f)

   while(!(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET));

   return (USART_ReceiveData(USART1));
}
我等著,大家有人能指出我的疑惑,因為VC的庫函數都封裝起來了,我在庫函數裡也沒有找到fputc
的函數原型,只有等著有人能給我指出來,謝謝!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.