usart.c的文件介绍:
官方给出的usart库函数:
使UASRT串口可用printf函数发送
在usart.h文件里可更换使用printf函数的串口号
对printf的相关设定
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE {
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
_sys_exit(int x){
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f){
while((USART_n->SR&0X40)==0);//循环发送,直到发送完毕
USART_n->DR = (u8) ch;
return ch;
}
#endif
USART1串口相关程序
USART使用与屏蔽选择
#if EN_USART1 //USART1使用与屏蔽选择
u8 USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
u16 USART1_RX_STA=0; //接收状态标记
USART1专用的printf函数
当同时开启2个以上串口时,printf函数只能用于其中之一,其他串口要自创独立的printf函数
调用方法:USART1_printf(“123”); //向USART1发送字符123
void USART1_printf (char *fmt, ...){
char buffer[USART1_REC_LEN+1]; // 数据长度
u8 i = 0;
va_list arg_ptr;
va_start(arg_ptr, fmt);
vsnprintf(buffer, USART1_REC_LEN+1, fmt, arg_ptr);
while ((i < USART1_REC_LEN) && (i < strlen(buffer))){
USART_SendData(USART1, (u8) buffer[i++]);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}
va_end(arg_ptr);
}
串口1初始化并启动
void USART1_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时钟
//USART1_TX PA.9
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);
//USART1_RX PA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
//Usart1 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 初始化设置(基本性能)
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);//开启ENABLE/关闭DISABLE中断 (串口中断)
USART_Cmd(USART1, ENABLE); //使能串口
}
还有串口中断服务程序,在需要串口中断时再写
usart2与usart3的相关程序函数与usart1类似,不再赘述。
usart.h中的相关设置
#define USART_n USART1 //定义使用printf函数的串口,其他串口要使用USART_printf专用函数发送
#define USART1_REC_LEN 200 //定义USART1最大接收字节数
#define USART2_REC_LEN 200 //定义USART2最大接收字节数
#define USART3_REC_LEN 200 //定义USART3最大接收字节数
//不使用某个串口时要禁止此串口,以减少编译量
#define EN_USART1 1 //使能(1)/禁止(0)串口1
#define EN_USART2 0 //使能(1)/禁止(0)串口2
#define EN_USART3 0 //使能(1)/禁止(0)串口3
usart的应用
usart的发送程序
int main (void){//主程序
u8 a=7,b=8;
//初始化程序
RCC_Configuration(); //时钟设置
USART1_Init(115200); //串口初始化(参数是波特率)
//主循环
while(1){
/* 发送方法1 */
// USART_SendData(USART1 , 0x55); //发送单个数值
// USART_SendData(USART1 , 'U'); //使用单引号与上面等价
// while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET); //检查发送中断标志位
/* 发送方法2 */
// printf("STM32F103 "); //纯字符串发送数据到串口
// printf("STM32 %d %d ",a,b); //纯字符串和变量发送数据到串口,a符号变量
/* 发送方法3 */
USART1_printf("STM32 %d",2);
// USART2_printf("STM32 %d",2);
// USART3_printf("STM32 %d",2);//使用usart2或者3时要先进行对应的初始化再使用
delay_ms(1000); //延时
}
}
usart的接收程序
方式一:查询方式
使用查询方式前,应关闭串口中断:在usart.c中设置
USART_ITConfig(USART1, USART_IT_RXNE,DISABLE);//关闭中断
int main (void){//主程序
u8 a;
//初始化程序
RCC_Configuration(); //时钟设置
USART1_Init(115200); //串口初始化(参数是波特率)
// USART1_IRQHandler();
//主循环
while(1){
// //查询方式接收
// if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) != RESET){ //查询串口待处理标志位
// a =USART_ReceiveData(USART1);//读取接收到的数据
// printf("%c",a); //把收到的数据发送回电脑
// }
//
// delay_ms(1000); //延时
}
}
查询方式实时性不足,反应时间长。
方式二:中断方式
使用中断方式前,应开启串口中断:在usart.c中设置
USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);//开启中断
当串口收到数据时,会跳转到串口中断程序。
中断函数写在usart.c中
void USART1_IRQHandler(void){ //串口1中断服务程序(固定的函数名不能修改)
u8 a;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){ //接收中断(接收到的数据必须是0x0d 0x0a结尾)
a =USART_ReceiveData(USART1);//读取接收到的数据
printf("%c",a); //把收到的数据发送回电脑
}
}
串口控制应用
结合串口发送与接收,并配置usart.h应用,注意相关硬件的初始化
int main (void){//主程序
u8 a;
//初始化程序
RCC_Configuration(); //时钟设置
LED_Init();//LED初始化
KEY_Init();//按键初始化
BUZZER_Init();//蜂鸣器初始化
USART1_Init(115200); //串口初始化(参数是波特率)
//主循环
while(1){
//查询方式接收
if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) != RESET){ //查询串口待处理标志位
a =USART_ReceiveData(USART1);//读取接收到的数据
switch (a){
case '0':
GPIO_WriteBit(LEDPORT,LED1,(BitAction)(0)); //LED控制
printf("%c:LED1 OFF ",a); //
break;
case '1':
GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1)); //LED控制
printf("%c:LED1 ON ",a); //
break;
case '2':
BUZZER_BEEP1(); //蜂鸣一声
printf("%c:BUZZER ",a); //把收到的数据发送回电脑
break;
default:
break;
}
}
//按键控制
if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //读按键接口的电平
delay_ms(20); //延时20ms去抖动
if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //读按键接口的电平
while(!GPIO_ReadInputDataBit(KEYPORT,KEY1)); //等待按键松开
printf("KEY1 "); //
}
超级终端串口控制程序
主程序
int main (void){//主程序
RCC_Configuration();
LED_Init();//LED初始化
KEY_Init();//按键初始化
BUZZER_Init();//蜂鸣器初始化
USART1_Init(115200); //串口初始化,参数中写波特率
USART1_RX_STA=0xC000; //初始值设为有回车的状态,即显示一次欢迎词
while(1){
if(USART1_RX_STA&0xC000){ //如果标志位是0xC000表示收到数据串完成,可以处理。
if((USART1_RX_STA&0x3FFF)==0){ //单独的回车键再显示一次欢迎词
printf("\033[1;47;33m\r\n"); //设置颜色(参考超级终端使用)
printf(" 1y--开LED1灯 1n--关LED1灯 \r\n");
printf(" 2y--开LED2灯 2n--关LED2灯 \r\n");
printf(" 请输入控制指令,按回车键执行! \033[0m\r\n");
}else if((USART1_RX_STA&0x3FFF)==2 && USART1_RX_BUF[0]=='1' && USART1_RX_BUF[1]=='y'){ //判断数据是不是2个,第一个数据是不是“1”,第二个是不是“y”
GPIO_SetBits(LEDPORT,LED1); //LED灯都为高电平(1)
printf("1y -- LED1灯已经点亮!\r\n");
}else if((USART1_RX_STA&0x3FFF)==2 && USART1_RX_BUF[0]=='1' && USART1_RX_BUF[1]=='n'){
GPIO_ResetBits(LEDPORT,LED1); LED灯都为低电平(0)
printf("1n -- LED1灯已经熄灭!\r\n");
}else if((USART1_RX_STA&0x3FFF)==2 && USART1_RX_BUF[0]=='2' && USART1_RX_BUF[1]=='y'){
GPIO_SetBits(LEDPORT,LED2); //LED灯都为高电平(1)
printf("2y -- LED2灯已经点亮!\r\n");
}else if((USART1_RX_STA&0x3FFF)==2 && USART1_RX_BUF[0]=='2' && USART1_RX_BUF[1]=='n'){
GPIO_ResetBits(LEDPORT,LED2); LED灯都为低电平(0)
printf("2n -- LED2灯已经熄灭!\r\n");
}else{ //如果以上都不是,即是错误的指令。
printf("指令错误!\r\n");
}
USART1_RX_STA=0; //将串口数据标志位清0
}
}
}
超级终端的串口中断:串口1中断服务程序(固定的函数名不能修改)
中断函数写在usart.c中
void USART1_IRQHandler(void){
u8 Res;
//以下是字符串接收到USART1_RX_BUF[]的程序,(USART1_RX_STA&0x3FFF)是数据的长度(不包括回车)
//当(USART1_RX_STA&0xC000)为真时表示数据接收完成,即超级终端里按下回车键。
//在主函数里写判断if(USART1_RX_STA&0xC000),然后读USART1_RX_BUF[]数组,读到0x0d 0x0a即是结束。
//注意在主函数处理完串口数据后,要将USART1_RX_STA清0
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){ //接收中断(接收到的数据必须是0x0d 0x0a结尾)
Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
printf("%c",Res); //把收到的数据以 a符号变量 发送回电脑
if((USART1_RX_STA&0x8000)==0){//接收未完成
if(USART1_RX_STA&0x4000){//接收到了0x0d
if(Res!=0x0a)USART1_RX_STA=0;//接收错误,重新开始
else USART1_RX_STA|=0x8000; //接收完成了
}else{ //还没收到0X0D
if(Res==0x0d)USART1_RX_STA|=0x4000;
else{
USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res ; //将收到的数据放入数组
USART1_RX_STA++; //数据长度计数加1
if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
}
#endif