目录
printf函数移植方法
显示汉字
串口发送
串口发送+接收
串口收发HEX数据包
串口收发文本数据包
//重定向到串口
int fputc(int ch,FILE *f)
{
Serial_SendByte(ch);
return ch;
}
2. 多串口可以使用sprintf
char String[100];
sprintf(String,"Num=%d\r\n",666);//可以指定打印位置,不涉及重定向
Serial_SendString(String);
3. 封装sprintf
头文件
/**
* @brief
* @param 参数1:格式化字符串 参数二:接受可变参数列表
* @retval
*/
void Serial_Printf(char *format,...)
{
char String[100];
va_list arg; //定义一个参数列表变量
va_start(arg,format);
vsprintf(String,format,arg);
va_end(arg);
Serial_SendString(String);
}
方法1:keil和串口助手都选择utf-8,且keil加上--no-multibyte-chars参数
方法2:都是用GB开头的中文编码格式,参数不用加
#include "stm32f10x.h" // Device header
#include
#include
void Serial_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //USART1在APB2上
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
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);
USART_InitTypeDef USART_InitStruct;
//写完波特率,init函数内部会自动算好波特率对应的分频系数写到BRR寄存器
USART_InitStruct.USART_BaudRate=9600;
USART_InitStruct.USART_HardwareFlowControl= USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode=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);
}
void Serial_SendByte(uint8_t byte)
{
USART_SendData(USART1, byte);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
void Serial_SendArray(uint8_t *Array,uint16_t Length)
{
uint16_t i;
for(i=0;i
定义一个结构体变量但要分别调用 GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitTypeDef GPIO_InitStructure;
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_IPU; 浮空输入或上拉输入
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
只支持1字节的接收
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; 浮空输入或上拉输入
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
1.查询模式
if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==SET)//可读取
{
data=USART_ReceiveData(USART1);
OLED_ShowHexNum(1,1,data,2);
}
2.中断模式
初始化代码
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //开启到NVIC通道
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStruct;
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);
uint8_t Serial_GetRxFlag(void)
{
if(Serial_RxFlag==1)
{
Serial_RxFlag=0;
return 1;
}
return 0;
}
uint8_t Serial_GetRxData(void)
{
return Serial_RxData;
}
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
{
Serial_RxData=USART_ReceiveData(USART1);
Serial_RxFlag=1;
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
主函数
if (Serial_GetRxFlag() == 1)
{
RxData = Serial_GetRxData();
Serial_SendByte(RxData);
OLED_ShowHexNum(1, 8, RxData, 2);
}
在上述代码基础上根据状态图在中断里进行接收数据 存入Serial_RXPacket[];(固定包长)
//状态机
void USART1_IRQHandler(void)
{
static uint8_t s=0;
static uint8_t pRXPacket=0;
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
{
uint16_t data=USART_ReceiveData(USART1);
if(s==0)
{
if(data==0XFF)
{
s=1;
pRXPacket=0;
}
}
else if(s==1)
{
Serial_RXPacket[pRXPacket]=data;
pRXPacket++;
if(pRXPacket>=4)
{
s=2;
}
}
else if(s==2)
{
if(data==0xFE)
{
s=0;
Serial_RxFlag=1;
}
}
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
//发送数据包
void Serial_SendPacket(void)
{
Serial_SendByte(0xFF);
Serial_SendArray(Serial_TXPacket,4);
Serial_SendByte(0xFE);
}
(可变包长)实现控制LED的亮灭
发送部分可以sendstring或者直接打印
//状态机
void USART1_IRQHandler(void)
{
static uint8_t s=0;
static uint8_t pRXPacket=0;
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
{
uint16_t data=USART_ReceiveData(USART1);
if(s==0)
{
//主函数里完成操作后置0,所以当主函数完成后才进行接收下一个数据包
if(data=='@'&& Serial_RxFlag == 0)
{
s=1;
pRXPacket=0;
}
}
else if(s==1)
{
if(data=='\r')
{
s=2;
}
else
{
Serial_RXPacket[pRXPacket]=data;
pRXPacket++;
}
}
else if(s==2)
{
if(data=='\n')
{
s=0;
Serial_RXPacket[pRXPacket]='\0'; //字符串结束
Serial_RxFlag=1;
}
}
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
主函数
while(1)
{
if(Serial_RxFlag==1) //收到完整的了,可以读出数据了
{
if(strcmp(Serial_RXPacket,"LED_ON")==0)
{
LED_ON(GPIO_Pin_1);
Serial_SendString("LED_ON_OK\r\n");
OLED_ShowString(1,1," ");
OLED_ShowString(1,1,"LED_ON");
}
else if(strcmp(Serial_RXPacket,"LED_OFF")==0){
LED_OFF(GPIO_Pin_1);
Serial_SendString("LED_OFF_OK\r\n");
OLED_ShowString(1,1," ");
OLED_ShowString(1,1,"LED_OFF");
}
else{
Serial_SendString("ERROR\r\n");
OLED_ShowString(1,1," ");
OLED_ShowString(1,1,"ERROR");
}
Serial_RxFlag=0;
}
}