1、新建一个工程模板
2、串口设置的一般步骤为:
1) 串口时钟使能,GPIO时钟使能
串口是挂载在 APB2 下面的外设,所以使能函数为: RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1);
2) 串口复位
当外设出现异常的时候可以通过复位设置,实现该外设的复位,然后重新配置 这个外设达到让其重新工作的目的。一般在系统刚开始配置外设的时候,都会先执行复位该外 设的操作。复位的是在函数 void USART_DeInit(USART_TypeDef* USARTx)中完成。复位串口1方法为:USART_DeInit(USART1)。
3) GPIO 端口模式设 置
4) 串口参数初始化
串口初始化是通过 USART_Init()函数实现的, void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
这个函数的的第一个入口参数是指定初始化的串口标号,这里选择 USART1。 第二个入口参数是一个 USART_InitTypeDef 类型的结构体指针,这个结构体指针的成员变量用 来设置串口的一些参数。
5) 开启中断并且初始化 NVIC(如果需要开启中断才这个步骤)
6) 使能串口
7) 编写中断处理函数
注:
(1)相关资料参考《STM32不完全手册-库函数版本》
(2)NVIC 为STM32优先级响应
1)如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将可能得到意想不到的结果;
2)抢占式优先级别相同的中断源之间没有嵌套关系;
3)如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优先级别,则可以为这个中断源指定任意有效的响应优先级别。 抢占优先级和响应优先级区别 当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。 如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。 当两个中断源抢占式优先级不同时,当正在处理的中断的抢占式优先级比后来的低,则后来的中断将会打断前一个中断处理,先处理后来的抢占式优先级较高的中断。 抢占式优先级与响应优先级,抢占式优先级是用于占先即可以中断比它较低抢占式优先级的中断处理过程。而响应优先级只在两个或多个中断源到达时,中断响应时起作用。
具体参考:http://wenku.baidu.com/view/152e160c7cd184254b35353e.html
3、具体程序分析
/********************************************************************************
主 函 数
*********************************************************************************/
/********************************************************************************
程序功能: 通过串口发送0、1,串口接收到之后使与PD2口相连接的LED灯实现亮灭的功能,
从而达到串口调试的目的。
*********************************************************************************/
int main(void)
{
u8 t;
u8 len;
u16 times=0;
delay_init(); //延时函数初始化
NVIC_Configuration();// 设置中断优先级分组
uart_init(9600); //串口初始化
LED_Init(); //初始化与LED连接的硬件接口
while(1)
{
if(USART_ReceiveData(USART1) == 0x30)
GPIO_SetBits(GPIOD,GPIO_Pin_2);
if(USART_ReceiveData(USART1) == 0x31)
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
}
/*********************************************************************************
Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此STM32把指定中断优先级的寄存器位减少到4位,这4个寄存器位的分组方式如下:
第0组:所有4位用于指定响应优先级
第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级
第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级
第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级
第4组:所有4位用于指定抢占式优先级
可以通过调用STM32的固件库中的函数NVIC_PriorityGroupConfig()选择使用哪种优先级分组方式,这个函数的参数有下列5种:
NVIC_PriorityGroup_0 => 选择第0组
NVIC_PriorityGroup_1 => 选择第1组
NVIC_PriorityGroup_2 => 选择第2组
NVIC_PriorityGroup_3 => 选择第3组
NVIC_PriorityGroup_4 => 选择第4组
**********************************************************************************/
void NVIC_Configuration(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
}
//初始化IO 串口1
//bound:波特率
void uart_init(u32 bound){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟 (1)GPIO时钟使能,串口时钟使能
USART_DeInit(USART1); //复位串口1 (2)串口复位
//USART1_TX PA.9 (3)GPIO端口模式设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
//USART1_RX PA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10
//Usart1 NVIC 配置 (4)初始化NVIC
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置 (5)串口参数初始化
USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
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_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断 (6)开启中断
USART_Cmd(USART1, ENABLE); //使能串口 (7)使能串口
}
/********************************************************************************
这个函数中又出现对NVIC的设置,我的理解是:
通过函数void NVIC_Configuration(void)设置中断优先级,然后在void uart_init(u32 bound)
中设置中断源的优先级。
也就是说中断优先级>中断源的优先级。只有先设置了中断优先级,才能设置中断源的优先级,这是一个包含关系。
*********************************************************************************/
在usart.c文件中,我将最后一部分程序修改为:
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
USART_SendData(USART1,Res);
}
意思就是说我写一个数据串口就立刻发送一个数据,当然,在例程中对这个发送过程有一个很详细的判断过程,但由于在我的电脑上调试出现问题,所以不得不进行这样的修改。出现的问题为:串口开始能正常接收数据,工作正常,后来就不能了,目前尚未发现问题出现的原因。所以我从串口通信的原理自己设计了一下我的主函数。
由于我已经知道我的数据能正常发送,所以我在主程序中直接对串口接收到的数据进行判断USART_ReceiveData(USART1) ,判断成立时就实现我想要的功能。
之前的那个问题困扰我比较久,导致没有什么进展。所以我最后不得不在懂得原理的情况下自己进行程序的编写,但结果是好的。只要原理理解,功能的实现就应该不难。