基于stm32f103zet6的串口學(xué)習(xí)
進(jìn)行串口配置的步驟
一、初始化GPIO,配置GPIO模式
一個(gè)結(jié)構(gòu)體
GPIO_InitTypeDef{
GPIOMode_TypeDef GPIO_Mode//GPIO模式,輸入,輸出?
uint16_t GPIO_Pin//哪個(gè)管腳?
GPIOSpeed_TypeDef GPIO_Speed//輸出響應(yīng)速度?如果為輸入則可以不設(shè)置
}
//GPIO_Mode包括以下幾種方式
Enumerator: 枚舉類型
GPIO_Mode_AIN //模擬輸入
GPIO_Mode_IN_FLOATING //懸浮輸入
GPIO_Mode_IPD //下拉輸入
GPIO_Mode_IPU //上拉輸入
GPIO_Mode_Out_OD //開(kāi)漏輸出
GPIO_Mode_Out_PP //推挽輸出//push pull 直接輸出為高低,當(dāng)選用開(kāi)漏的時(shí)候需要外接三極管
GPIO_Mode_AF_OD //復(fù)用開(kāi)漏輸出
GPIO_Mode_AF_PP //復(fù)用推挽輸出
//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的模式有以下幾種,同樣是一個(gè)枚舉類型
Output Maximum frequency selection.
Enumerator:
GPIO_Speed_10MHz
GPIO_Speed_2MHz
GPIO_Speed_50MHz
//TXD為輸出,RXD為浮空輸入
//選用usart1的時(shí)候管腳應(yīng)該是PA9(TXD),PA10(RXD)
//所以不難得出,初始化的時(shí)候它的設(shè)計(jì)語(yǔ)句應(yīng)該是
//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;
那么至此為止,我的猜測(cè)GPIO初始化完畢,驗(yàn)證一下!
/* 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);
看來(lái)問(wèn)題不是很大,只是最后需要加上 GPIO_Init(GPIOA, &GPIO_InitStructure);
來(lái)指定對(duì)哪個(gè)GPIO進(jìn)行初始化!
二、接下來(lái)初始化串口
// USART_InitTypeDef USART_InitStructure;//定義串口初始化結(jié)構(gòu)體
還一個(gè)結(jié)構(gòu)體
USART_InitTypeDef{
uint32_t USART_BaudRate//波特比率
uint16_t USART_HardwareFlowControl//硬件流,所謂硬件流待查證
uint16_t USART_Mode//串口模式,這個(gè)比較豐富
uint16_t USART_Parity//雖然不認(rèn)識(shí),但是參測(cè)應(yīng)該是奇偶校驗(yàn)位
uint16_t USART_StopBits//停止位
uint16_t USART_WordLength//長(zhǎng)度
}
1、一個(gè)一個(gè)進(jìn)行分析,首先是USART_BaudRate
先來(lái)一個(gè)計(jì)算表達(dá)式,這個(gè)和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)))//整數(shù)部分
FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5//小數(shù)部分
//這里涉及到另外一個(gè)結(jié)構(gòu)體USART_InitStruct,跟蹤下去,發(fā)現(xiàn)這是同一個(gè)結(jié)構(gòu)體,按就好辦了!直接根據(jù)波特率
//就能計(jì)算出其整數(shù)部分和小數(shù)部分,它可以取的數(shù)雖然多,但是有誤差大小之分!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)//據(jù)介紹應(yīng)該是不使用硬件流
#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)//無(wú)奇偶標(biāo)志位
#define USART_Parity_Odd ((uint16_t)0x0600)
5、USART_StopBits、USART_WordLength這兩個(gè)很明顯,不解釋了!
分析上面之后基本上能夠確定串口的配置了
//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
最后幾句就是我們常說(shuō)的8N1
下面來(lái)驗(yàn)證一下!
/* 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);
/*問(wèn)題還是有不少啊
1、首先是波特率搞錯(cuò)應(yīng)該是115200 不是 11520
2、然后是模式選錯(cuò),全雙工應(yīng)該是USART_Mode_Rx | USART_Mode_Tx;
3、串口只是配置了,又沒(méi)有初始化
4、還有串口沒(méi)有使能
三、第一第二步之后,串口初始化完,下面我們就需要使用到串口了,是否還是像以前的單片機(jī)那樣,
如果想要向串口發(fā)送數(shù)據(jù)就直接寫個(gè)函數(shù),個(gè)BUFF里面寫數(shù)據(jù)呢?不,那效率太低了,我們使用到printf函數(shù)
系統(tǒng)庫(kù)函數(shù)調(diào)用,下面就需要重定向!
1、我再arm11的參考書上面了解到,所謂重定向就是指,本來(lái)如果調(diào)用系統(tǒng)庫(kù)的話,那么printf函數(shù)答應(yīng)的
信息是顯示到調(diào)試器窗口的,但是當(dāng)我們重定向后,打印的信息就是在串口里面了,同時(shí)也能實(shí)現(xiàn)到彩屏上
去。
2、調(diào)用庫(kù)函數(shù)必須包含stdio.h函數(shù),現(xiàn)在來(lái)跟蹤一下這個(gè)printf函數(shù)到底有什么東西
#include
#include
#include
/* 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;
}
繼續(xù)看
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 = "
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 = '