/******************************************************************/
/**************************** STM32开发 *************************/
/**************************** 串口实验 *************************/
/******************************************************************/
#include <stm32f10x_lib.h>
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
int main(void)
{
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
usart_init(72,115200); //串口初始化为115200
LED_Init(); //初始化与LED连接的硬件接口
while(1)
{
GetInputString(USART_RX_BUF);
printf("\r\n您输入的信息为:[%s]\n\r",USART_RX_BUF);
}
}
/**
* @brief Get Input string from the HyperTerminal
* 从超级终端输入字符串
* @param buffP: The input string
* @retval None
**/
void GetInputString(u8 *buffp)
{
u32 byte_mark=0; //定义一个标记第几个字符的变量byte_mark
u8 c=0;
do
{
c=GetKey();
if(c=='\r') //"Enter"键功能,回车换行
break;
if(c=='\b') //“Backspace”键功能
{
if(byte_mark>0)
{
printf("\b \b"); //第一步,将光标移到前一列。第二步,用空格符覆盖当前列
byte_mark--; //第三步,再将光标移到前一列。
}
continue;
}
if(byte_mark>=(CMD_STRING_SIZE))
{
printf("Command String size overflow\r\n");
byte_mark=0;
continue;
}
if(c>=0X20&&c<=0X7E)
{
buffp[byte_mark++]=c;
SerialPutChar(c); //将字符串一个一个输出
}
}
while(1);
printf("\n\r");
buffp[byte_mark]='\0';
}
/**
* @brief Wait until Get a key from the HyperTerminal
* 从超级终端获取字符串
* @param None
* @retval The Key Pressed
**/
u8 GetKey(void)
{
u8 key=0;
while (1)
{
if(SerialKeyPressed((u8*)&key))
break;
}
return key;
}
/**
* @brief Test to see if a key has been pressed on the HyperTerminal
* 检测是否有字符 从超级终端 键入
* @param key: The key pressed
* @retval 1: Correct
* 0: Error
**/
u32 SerialKeyPressed(u8 *key)
{
/* 当接收移位寄存器中的数据被转移到接收数据寄存器(RDR)里面时,
* USART1->SR里面的RXNE=1(表示收到数据),即USART1->SR&0X20=1 。
*/
if ((USART1->SR&0X20)!=0)
{
*key=(u8)USART1->DR&0xFF;
return 1; //表示收到数据,可以读出
}
else
{
return 0; //表示没有收到数据
}
}
/**
* @brief Print a character on the HyperTerminal
* @param c: The character to be printed
* @retval None
* 如果数据发送完成,USART1->SR的TC位便会置1,即TC=1。
* 然后退出循环。
**/
void SerialPutChar(u8 c)
{
USART1->DR=(c&(u16)0x01FF); //发送数据c
while((USART1->SR&0X40)==0); //等待发送结束,TC=1时,表示数据发送完成
}
/********************************STM32开发************************************/
/*******************************串口1初始化***********************************/
#include "sys.h"
#include "usart.h"
/****************************************************************************/
/************* 支持适应不同频率下的串口波特率设置 ***********/
/************* 加入了对printf的支持 ***********/
/************* 增加了串口接收命令功能 ***********/
/*************加入以下代码,支持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()以避免使用半主机模式
_sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
USART1->DR = (u8) ch;
while((USART1->SR&0X40)==0); //循环发送,直到发送完毕
return ch;
}
#endif
//end
#ifdef EN_USART1_RX //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[CMD_STRING_SIZE]; //接收缓冲,最大64个字节.
//接收状态
//bit7,接收完成标志
//bit6,接收到0x0d
//bit5~0,接收到的有效字节数目
u8 USART_RX_STA=0; //接收状态标记
void USART1_IRQHandler(void)
{
u8 res;
if(USART1->SR&(1<<5)) //接收到数据
{
res=USART1->DR;
if((USART_RX_STA&0x80)==0)//接收未完成
{
if(USART_RX_STA&0x40) //接收到了0x0d
{
if(res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
else USART_RX_STA|=0x80; //接收完成了
}
else //还没收到0X0D
{
if(res==0x0d)USART_RX_STA|=0x40;
else
{
USART_RX_BUF[USART_RX_STA&0X3F]=res;
USART_RX_STA++;
if(USART_RX_STA>63)USART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
}
#endif
//初始化IO 串口1
//pclk2:PCLK2时钟频率(Mhz)
//bound:波特率
//CHECK OK
//091209
void usart_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=0X444444B4; //IO状态设置
RCC->APB2RSTR|=1<<14; //复位串口1
RCC->APB2RSTR&=~(1<<14); //停止复位
//波特率设置
USART1->BRR=mantissa; // 波特率设置
USART1->CR1|=0X200C; //1位停止,无校验位.
#ifdef EN_USART1_RX //如果使能了接收
//使能接收中断
USART1->CR1|=1<<8; //PE中断使能
USART1->CR1|=1<<5; //接收缓冲区非空中断使能
MY_NVIC_Init(3,3,USART1_IRQChannel,2); //组2,最低优先级
#endif
}
/******************************************************************/
/******************************************************************/
#ifndef __USART_H
#define __USART_H
#include <stm32f10x_lib.h>
#include "stdio.h"
//STM32开发板
//串口1初始化
#define CMD_STRING_SIZE 64
extern u8 USART_RX_BUF[CMD_STRING_SIZE]; //接收缓冲,最大63个字节.末字节为换行符
extern u8 USART_RX_STA; //接收状态标记
#define EN_USART1_RX //使能串口1接收
void usart_init(u32 pclk2,u32 bound);
void GetInputString(u8 *buffp);
void SerialPutChar(u8 c);
u32 SerialKeyPressed(u8 *key);
u8 GetKey(void);
#endif
问题是:输入字符串时很慢,有时候字符串输入不了;按回车输出的时候 Enter键要按很多次才能显示在超级终端上。
比如,我连续输入10次j ,结果终端上只显示2个。
不知道是哪里的问题,跪求各位的帮助! |