提示:这里可以添加本文要记录的大概内容:
目前已经学习了GPIO的输入输出,但是没有完整的显示信息,最便宜的显示就是串口。
000 -111
AVR单片机 已经学会过了,
提示:以下是本篇文章正文内容,下面案例可供参考
https://www.bilibili.com/video/BV1y34y147s5/?spm_id_from=333.337.search-card.all.click
https://www.bilibili.com/video/BV1PD4y147ts/?spm_id_from=autoNext
https://www.bilibili.com/video/BV14k4y187e6/?spm_id_from=autoNext
目标
USART_DR类似51单片机的SBUF
//开启串口1和GPIOA.9 10的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_USART1, ENABLE);
//2.配置GPIO
GPIO_InitStruct.GPIO_Pin= GPIO_Pin_9; //TX
GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct); //&x
GPIO_InitStruct.GPIO_Pin= GPIO_Pin_10; //RX
GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStruct); //&x
代码如下(示例):
// 3.配置USART
USART_InitStruct.USART_BaudRate= 9600;
USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
USART_InitStruct.USART_Parity= USART_Parity_No;
USART_InitStruct.USART_StopBits= USART_StopBits_1;
USART_InitStruct.USART_WordLength= USART_WordLength_8b;
USART_Init( USART1, &USART_InitStruct);
USART_Cmd(USART1, ENABLE);
USART_SendData(USART1, 'A');
// 5. 发送
USART_SendData(USART1, 'A');
//加入等待发送完成
// 没发送完成就一直是0,发送完成就是1
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
//while(!USART_GetFlagStatus(USART1, USART_FLAG_TC));
//while(!USART_GetFlagStatus(USART1, USART_FLAG_TC));
USART_SendData(USART1, 'B');
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
USART_SendData(USART1, 'C');
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
USART_SendData(USART1, 'D');
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
USART_SendData(USART1, 'E');
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
USART_SendData(USART1, 'F');
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
字符串最后一位就是 0,NULL
U8 ta[]="123";
send_string(ta); //这时候ta代表装着 123数据的首地址,1的地址,*p就是1,p就是1的地址也首地址,ta;
void send_string(u8 *p)
{
while(*p !=0)
{
USART_SendData(USART1, *p);
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
p++;
}
}
需要重定向一个函数,让printf 发送到串口而不是C语言里面的控制台
加头文件
#include “stdio.h”
int fputc(int ch,FILE *f)
{
USART_SendData(USART1, (u8)ch);
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
return ch;
}
单独写这个不能发送
要勾选
printf("STM32简答吗?");
printf("STM32简答吗?\r\n");
printf("STM32简答吗?能考%d 分?\r\n",60);
串口中断数据接收有2种方法,为了节省资源,一般采用中断的方法
void main()
{
while(1)
{
if(串口接收完成)
{
temp= 接收函数
}
}
}
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd= ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority= 1;
NVIC_Init(&NVIC_InitStruct);
第三步
USART_ITConfig( USART1, USART_IT_RXNE, ENABLE);
第四步
void USART1_IRQHandler() //中断函数
{
u16 temp;
if(USART_GetITStatus( USART1, USART_IT_RXNE)) //判断是否是接收完成中断
{
temp=USART_ReceiveData(USART1); //接收数据
USART_SendData(USART1, temp); //发送收据
USART_ClearITPendingBit(USART1, USART_IT_RXNE); //清楚接收完成中断
}
}
如何解决问题
解决方法:
成功的案列
使用串口交互代码问题
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "USART.h"
#include "LED.h"
#include "string.h"
#include "stdio.h"
uint8_t Data;//接收一字节数据
unsigned char RX_Str[100];
unsigned char ta[100]={"1234我的名字"};
u16 Rx_FLAG=0; //接收完成标志位
unsigned char hongdeng[]={"红灯"};
int main()
{
USART_INT();//串口初始化
LED_int();//LED初始化
USART_SendData(USART1,'a');//串口能正确接收说明硬件、软件没问题
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
printf("你好吗\r\n");//打印红灯亮信息 红灯亮 \r\n换行
//串口能正确发送说明 发送编码没问题
while(1)
{
if(Rx_FLAG==1)//接收完成标志 Rx_FLAG 为 1
{
if(strcmp(RX_Str,"红灯")==0)//比对接收的字符是否为 红灯
{
LEDR_ON();//红灯亮
printf("红灯亮 \r\n");//打印红灯亮信息 红灯亮 \r\n换行
}
else if(strcmp(RX_Str,"蓝灯")==0)//比对接收的字符是否为 蓝灯
{
LEDB_ON();//蓝灯亮
printf("蓝灯亮 \r\n");//打印蓝灯亮信息 蓝灯亮
}
else if(strcmp(RX_Str,"绿灯")==0)//比对接收的字符是否为 绿灯
{
LEDG_ON();//绿灯亮
printf("绿灯亮 \r\n");//打印绿灯亮信息 绿灯亮
}
else if(strcmp(RX_Str,"关灯")==0)//比对接收的字符是否为 关灯
{
LED_ALLOFF();//灯全灭
printf("已关灯 \r\n");//打印灯灭信息 已关灯
}
else if(strcmp(RX_Str,"我的学号")==0)//比对接收的字符是否为 我的学号
{
printf("学号:2015252525225 \r\n");//打印 学号:2015252525225
}
else if(strcmp(RX_Str,"我的姓名")==0)//比对接收的字符是否为 我的姓名
{
printf("姓名:xxx \r\n");//打印
}
else //若输入指令都不符合 则打印输入指令错误
{
printf("输入指令错误!! \r\n");//打印输入指令错误
}
Rx_FLAG=0;//接收完成标志位置0
}
}
}
/*
通过接收HEX数据包实现交互 包头@ 数据1 数据2 ... 包尾\r\n
利用状态转换思想接收HEX数据包 相当于数电的状态转换 等待转换信号来临进而转换状态
*/
void USART1_IRQHandler() //串口中断函数
{
static u16 RX_zt;//串口接收状态
static u16 i;//字符数组下标
if (USART_GetITStatus(USART1, USART_IT_RXNE)==SET)//当接收标志位为SET 开始接收
{
Data=USART_ReceiveData(USART1);//接收数据
if(RX_zt==0)//若串口接收状态为状态0
{
if(Data==' '&&Rx_FLAG==0)//判断接收到的数据是否为包头 @ 在Rx_FLAG=0情况下接收数据防止数据传输过快错乱
{
RX_zt=1;//转换为状态1
i=0;//字符数组下标置0
}
}
// 123132\r\n
else if(RX_zt==1)//若串口接收状态为状态1
{
if(Data=='\r')//判断是否为包尾字符 不定长HEX数据包接收数据需时刻比对包尾信号
{
RX_zt=2;//转换为状态2
}
else
{
RX_Str[i]=Data;//接收数据存入字符数组
i++;
}
}
else if(RX_zt==2)//若串口接收状态为状态2
{
if(Data=='\n')//再次判断是否为包尾字符
{
RX_zt=0;//转换为状态0
RX_Str[i]='\0';//字符串接收结束
Rx_FLAG=1;//接收完成标志位置1
}
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE);//清除接收标志位
}
}
strcmp函数讲解
https://baike.baidu.com/item/strcmp/5495571?fr=ge_ala
https://blog.csdn.net/qq_44852376/article/details/128460223
核心问题:32用的是UTF-8编码 ->上位机用的是ANSI编码
新建工程,一开始就用ANSI编码,中间不要随意改动编码
使用nopepad++软件实现
实现对话,发送名字,学号,指定三盏灯的状态,
最有加入了 发送和回复的功能,为上位机 通信奠定了基础!