目录
初始化GPIO
需要将USART1对应的引脚配置成相应的模式:
RCC->APB2ENR|=1<<2; //使能PORTA口时钟
GPIOA->CRH&=0XFFFFF00F; //IO状态设置
GPIOA->CRH|=0X000008B0; //IO状态设置
初始化串口
将USART1配置成:波特率9600、1位停止位、8位数据位、无校验位、使能接收中断、接收使能、发送使能
代码可以是这样:
void uart_init(u32 pclk2,u32 bound)
{
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
mantissa=temp; //得到整数部分
fraction=(temp-mantissa)*16; //得到小数部分
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR|=1<<14; //使能串口时钟
RCC->APB2RSTR|=1<<14; //复位串口1
RCC->APB2RSTR&=~(1<<14);//停止复位
//波特率设置
USART1->BRR=mantissa; // 波特率设置
USART1->CR1|=0X200C; //1位停止,无校验位.
//使能接收中断
USART1->CR1|=1<<5; //接收缓冲区非空中断使能
MY_NVIC_Init(0,0,USART1_IRQn,0);//组0,最高优先级
}
重定向fput函数
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//等待上一次串口数据发送完成
USART1->DR = (u8) ch; //写DR,串口1将发送数据
return ch;
}
加入以下代码,支持printf函数,而不需要选择use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
/* FILE is typedef’ d in stdio.h. */
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
如果不加入上面这段代码,则需要在KEIL中选择use MicroLIB:
要加入头文件:#include "stdio.h"
fputc是重定向printf的输出设备,重定向fputc之后可以直接使用printf将需要发送的数据通过串口发送出去。比如说发送浮点数,长整数等不是八位的数据时,使用printf就可以很方便的发送数据。
USART1中断函数
void USART1_IRQHandler(void)
{
u8 res;
res=USART1->DR;
}
USART1完整代码
USART1每秒发送一次hello world,并将接收到的数据发送回去
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "stdio.h" //使用MicroLIB
void uart_init(u32 pclk2,u32 bound)
{
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
mantissa=temp; //得到整数部分
fraction=(temp-mantissa)*16; //得到小数部分
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR|=1<<2; //使能PORTA口时钟
RCC->APB2ENR|=1<<14; //使能串口时钟
GPIOA->CRH&=0XFFFFF00F;//IO状态设置
GPIOA->CRH|=0X000008B0;//IO状态设置
RCC->APB2RSTR|=1<<14; //复位串口1
RCC->APB2RSTR&=~(1<<14);//停止复位
//波特率设置
USART1->BRR=mantissa; // 波特率设置
USART1->CR1|=0X200C; //1位停止,无校验位.
//使能接收中断
USART1->CR1|=1<<5; //接收缓冲区非空中断使能
MY_NVIC_Init(3,3,USART1_IRQn,2);//组2,最低优先级
}
void USART1_IRQHandler(void)
{
u8 res;
res=USART1->DR;
while(!(USART1->SR&(1<<6)));
USART1->DR = res;
}
int main(void)
{
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
uart_init(72,9600); //串口初始化为9600
while(1)
{
printf("hello world\n");
delay_ms(1000);
}
}
库函数的代码
#include "stm32f10x.h" // Device header
#include "delay.h"
#include "stdio.h"
int fputc(int ch, FILE *f)
{
USART_SendData(USART1 , (u8)ch);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
return ch;
}
void USART1_IRQHandler(void)
{
printf("%c",USART_ReceiveData(USART1));
}
void USART1_Init(void)
{
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure; //USART1 PA9-TX PA10-RX
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA , ENABLE); //时钟使能
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA , &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA , &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1 , &USART_InitStructure);
USART_Cmd(USART1 , ENABLE);
USART_ITConfig(USART1 , USART_IT_RXNE , ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);
}
int main(void)
{
USART1_Init();
while(1)
{
printf("hello world\n");
Delay_ms(1000);
}
}