《《《《《正文》》》》》
《前言》
基于UART的串口在实际项目中的应用相当广泛,包括wifi、can、lin等均可使用uart进行通信,方便且成本低;而uart串口功能不仅仅体现在产品使用功能上,在开发调试阶段更是一个必不可少的调试助手。今天就来构建一个基于uart的调试串口功能模块;
开发需求:使用stm32f103的usart模块开发一个具有发送任意字符串的调试串口功能的模块;
相关代码获取地址:
https://pan.baidu.com/s/1zyrOF18WxIq0H3_4qU7Evg
关注公众号,发送1234,获取提取码;
《硬件设计》
TX | PA9 |
RX | PA10 |
《加载USART库文件》
《软件设计》
第一步:中断等级配置函数
void NvicConfig(void)
{
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn; //USART中断通道
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2; //设置抢占优先级为0
NVIC_InitStruct.NVIC_IRQChannelSubPriority=1; //设置子优先级为1
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; //使能外USART中断通道
NVIC_Init(&NVIC_InitStruct); //中断优先级初始化函数
}
第二步:串口初始化函数
//传入参数为波特率
void USART_init(uint32_t baudrate)
{
GPIO_InitTypeDef GPIO_InitStruct; //定义GPIO结构体变量
USART_InitTypeDef USART_InitStruct; //定义串口结构体变量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE); //使能GPIOA、USART1的时钟
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9; //配置TX引脚
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; //配置PA9为复用推挽输出
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; //配置PA9速率
GPIO_Init(GPIOA,&GPIO_InitStruct); //GPIO初始化函数
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10; //配置RX引脚
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING; //配置PA10为浮空输入
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; //配置PA10速率
GPIO_Init(GPIOA,&GPIO_InitStruct); //GPIO初始化函数
USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx; //发送接收模式
USART_InitStruct.USART_Parity=USART_Parity_No; //无奇偶校验
USART_InitStruct.USART_BaudRate=baudrate; //波特率
USART_InitStruct.USART_StopBits=USART_StopBits_1; //停止位1位
USART_InitStruct.USART_WordLength=USART_WordLength_8b; //字长8位
USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //无硬件数据流控制
USART_Init(USART1,&USART_InitStruct); //串口初始化函数
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //串口接收中断
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE); //串口空闲中断
USART_Cmd(USART1,ENABLE); //使能USART1
}
第三步:中断处理函数
void USART1_IRQHandler(void)
{
uint8_t clear = clear; //定义这个变量是针对编译出现“没有用到这个变量”的警告提示
uint8_t res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
{
res = USART1->DR;
//在此做数据接收处理
}
else if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //空闲中断
{
clear = USART1->SR; //读SR寄存器
clear = USART1->DR; //读DR寄存器(先读SR,再度DR,就是为了清除IDIE中断)
}
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
第四步:写发送数据函数
void usart_send(uint8_t *data,uint8_t len)
{
uint8_t i;
for(i=0;i<len;i++)
{
USART_SendData(USART1,*(data+i));
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
}
}
第五步:来个简单的测试,主函数:
int main(void)
{
uint8_t usartSendbuf[5] = {1,2,3,4,5};
NvicConfig();
USART_init(115200);
for(;;)
{
usart_send(usartSendbuf,5);
}
}
结果:
《printf函数重定向》
重定向函数:
int fputc(int ch,FILE *f) //printf重定向函数
{
USART_SendData(USART1,(uint8_t)ch); //发送一字节数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); //等待发送完成
return ch;
}
我们这里直接写是不行,因为这是C库自带的东西,但是可以重定向到这个函数(printf()在c标准库函数实质是一个宏,实际是调用fputc()函数),fputc()函数默认是把字符输出到调试器控制窗口,所以要想把数据通过USART输出到串口助手,需对基于fputc()的printf()系列函数的输出重定向到USART端口上去。
这里特别注意:打开“Options for target...”->“target”勾选“Use MiclroLIB” 不然用printf会有问题;
最后上测试函数:
int main(void)
{
NvicConfig();
USART_init(115200);
for(;;)
{
printf("System Init Finish\n");
printf("我正在测试\n");
}
}
结果:
《《《《《END》》》》》
转载:https://blog.csdn.net/qq_22520215/article/details/115802140
查看评论