【STM库应用】stm32 之 USART

STM库是官方提供的,其已经做好了底层驱动的配置,用起来是相当简单的;我们只需要了解其每个函数的功能,已经每个函数所使用流程即可!

整个框架就是下面这幅图,我们只需在顶层做调用即可,跟现在做app的差不多!

【STM库应用】stm32 之 USART_第1张图片

注:摘自野火,希望大哥不要说我盗版

刚刚开始拿道库,一看这么多函数,感觉有点棘手,无从下手;多亏stm官方也针对该库提供了一个应用手册,画了两天时间进行了探索和实践,发现了一点比较方便的诀窍。

在此给大家分享分享,我们就拿今天的USART来说吧!

至于建工程,网上以及教程里面是非常多的,我也就不多说了!

任意一个外设都对应一个ppp.c和ppp.h文件,所以我们其实也不是无章可循的!同时,stm库他有一套自己的缩写定义,我们必须记住,不过这个很好记!

【STM库应用】stm32 之 USART_第2张图片

同时他的函数命名也有一定的规则:

名为PPP_Init的函数,其功能是根据PPP_InitTypeDef中指定的参数,初始化外设PPP,例如  TIM_Init. 

名为PPP_DeInit的函数,其功能为复位外设PPP的所有寄存器至缺省值,例如  TIM_DeInit. 
名为PPP_StructInit的函数,其功能为通过设置PPP_InitTypeDef 结构中的各种参数来定义外设的功能,例如:USART_StructInit
名为PPP_Cmd的函数,其功能为使能或者失能外设PPP,例如:  SPI_Cmd. 
名为PPP_ITConfig的函数,其功能为使能或者失能来自外设PPP某中断源,例如:  RCC_ITConfig. 
名为PPP_DMAConfig的函数,其功能为使能或者失能外设PPP的DMA接口,例如:TIM1_DMAConfig. 
用以配置外设功能的函数,总是以字符串“Config”结尾,例如GPIO_PinRemapConfig. 
名为PPP_GetFlagStatus的函数,其功能为检查外设PPP某标志位被设置与否,例如:I2C_GetFlagStatus. 
名为PPP_ClearFlag的函数,其功能为清除外设PPP标志位,例如:I2C_ClearFlag. 
名为PPP_GetITStatus的函数,其功能为判断来自外设PPP的中断发生与否,例如:I2C_GetITStatus. 
名为PPP_ClearITPendingBit 的函数 , 其功能 为 清除外 设PPP 中断待处理标志位,例如:I2C_ClearITPendingBit. 

这些在官方给的库说明里面都有,我只是特别说明下,有助于我么了解!

我们经常用的不多,如:PPP_Init,PPP_Cmd,PPP_ITConfig,PPP_DMAConfig,PPP_GetFlagStatus,PPP_ClearFlag

同时我们需要熟悉的结构体:PPP_InitTypeDef等

上面指出的都是常用的,不多6个函数,1个结构体,相信大家应该能很快记住,我比较笨,记了两天才记的还不是很清!

下面我们先把USART1d的代码附上去!

void usart_config()
{
	USART_InitTypeDef usart;
	NVIC_InitTypeDef nvic;
	
	RCC->APB2ENR |= 1<<2;
	RCC->APB2ENR |= 1<<14;
	GPIOA->CRH &= ~(0xff<<4);
	GPIOA->CRH |= 0x8b<<4;
	
	usart.USART_BaudRate = 9600;
	usart.USART_Parity = USART_Parity_No;
	usart.USART_StopBits = USART_StopBits_1;
	usart.USART_WordLength = USART_WordLength_8b;
	usart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_Init(USART1,&usart);
	USART_Cmd(USART1,ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	nvic.NVIC_IRQChannel = USART1_IRQn;
	nvic.NVIC_IRQChannelCmd = ENABLE;
	nvic.NVIC_IRQChannelPreemptionPriority = 0x0f;
	nvic.NVIC_IRQChannelSubPriority = 0x0f;
	NVIC_Init(&nvic);
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	
}

怎么说呢,我是比较懒的!所以我比喜欢别人那种命名变量的方式,我以前是做linux的,我喜欢linux那套命名模式!

另外,我建议大家在做开发的时候用Keil4.0以上的版本,为啥呢?下面正式我想说的

我们在声明一个结构体变量的时候,我们不知道结构题里面每个变量的名字,怎么办?找吗?很麻烦是吧?

如果我们用了mdk4.0以上的版本,他会自动匹配

【STM库应用】stm32 之 USART_第3张图片

可能有的人用过了,会说我多余,呵呵但是对那些没有用过的人很有用,比如李想老师!呵呵,开个玩笑

这样我们就不用一个一个输入了!但是后面的变量赋值怎么办?其实这些变量赋值都在ppp.h里面定义好了,我大致看了下ppp.h内容不是很多,所以很容易就找到,我有一个方法就是查找!

比如我们要找USART_Mode所对应的赋值:

【STM库应用】stm32 之 USART_第4张图片

切换到stm32f10x_usart.h,直接在上面输入USART_Mode,按下Enter键,就找到了,那么我就直接把这个定义赋值过去,好了!

有人说我函数名记不住,那么我们还是在stm32f10x_usart.h直接一下子拉到最下面!是不是看到了所有的函数?

【STM库应用】stm32 之 USART_第5张图片

如果你细心看我代码的话,你会发现,我对GPIO的初始化没有用结构图,我发现直接配置管脚的话很方便,代码不多,我4行能解决他十几行的代码!

RCC->APB2ENR |= 1<<2;
RCC->APB2ENR |= 1<<14;
GPIOA->CRH &= ~(0xff<<4);
GPIOA->CRH |= 0x8b<<4;

这样就把整个配置完了!有的人说我能记住吗?这么多位!我只想呵呵!不信你自己对着寄存器看下

比如输入模式:后两位一定是00b,输出模式一定是其他三种!在输出中00,01为通用,10,11为复用,偶数为推挽,奇数为开漏,好记吧?

在输入中,有三种模式,浮空就是复位的时候,还有模拟输入,还有上拉下拉输入!

我今天想写中断函数,怎么办?记不住啊,我想既然是中断函数,他一定在启动代码里面有定义,直接切换到startup_stm32f10x.md.s里面,直接搜索Handler

找到所有中断函数的定义:

【STM库应用】stm32 之 USART_第6张图片

有了这些基本思想,我们在写程序的时候方便多了,这次完成串口的配置就用了半个小时!我只能说库用着好方便!

/*******************************************************************************
  * @file    obj/main.c 
  * @author  ieczw
  * @version V1.0.1
  * @date    24-11-2013
  *******************************************************************************/  

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "stdio.h"
#include "stm32f10x_conf.h"
void usart_config(void);
void led_init(void);
void msleep(u16 timeout);
void rs232_send_byte(u8 byte);
u16  systick = 0;
int main(void)
{
	u8 ascii = 0;
	SysTick_Config(72000);	//Config DiDa = 1ms
  /* Add your application code here */
	usart_config();
	led_init();
  /* Infinite loop */
	GPIOC->BRR |= 0xff<<8;
	msleep(1000);
	GPIOC->BSRR |= 0xff<<8;
	
  while (1)
  {
		rs232_send_byte(ascii++);
		msleep(1000);
  }
}

void led_init()
{
	RCC->APB2ENR |= 3<<4;
	GPIOC->CRH = 0x33333333;
	GPIOD->CRL &= ~(0xf<<2);
	GPIOD->CRL |= 3<<2;
	GPIOD->ODR &= ~(1<<2);
	GPIOC->ODR |= 0xff<<8;
}
void usart_config()
{
	USART_InitTypeDef usart;
	NVIC_InitTypeDef nvic;
	
	RCC->APB2ENR |= 1<<2;
	RCC->APB2ENR |= 1<<14;
	GPIOA->CRH &= ~(0xff<<4);
	GPIOA->CRH |= 0x8b<<4;
	usart.USART_BaudRate = 9600;
	usart.USART_Parity = USART_Parity_No;
	usart.USART_StopBits = USART_StopBits_1;
	usart.USART_WordLength = USART_WordLength_8b;
	usart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_Init(USART1,&usart);
	USART_Cmd(USART1,ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	nvic.NVIC_IRQChannel = USART1_IRQn;
	nvic.NVIC_IRQChannelCmd = ENABLE;
	nvic.NVIC_IRQChannelPreemptionPriority = 0x0f;
	nvic.NVIC_IRQChannelSubPriority = 0x0f;
	NVIC_Init(&nvic);
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	
}
void rs232_send_byte(u8 byte)
{
	USART_SendData(USART1,byte);
	while(RESET == USART_GetFlagStatus(USART1,USART_FLAG_TXE));
}
void USART1_IRQHandler(void)
{
	static u8 flag = 0;
	flag = ~flag;
	if(flag)
		GPIOC->BRR |= 0xff<<8;
	else
		GPIOC->BSRR |= 0xff<<8;
	if(USART1->SR&(1<<5))
	{
		USART1->DR = USART1->DR;
		while(0 == (USART1->SR&(1<<6)));
	}
}
void msleep(u16 timeout)
{
	systick = timeout;
	while(systick);
}

今天就是说库如何使用,原理请看 http://blog.csdn.net/ieczw/article/details/16118387

希望各位指点!




你可能感兴趣的:(stm32,STM32开发)