一、串口发送
1.初始化引脚
void Serial_Init(uint32_t BaudRate)
{
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA ,ENABLE );
RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1 ,ENABLE );
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;//由于PIN9为TX,故初始化为发送引脚
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init (GPIOA ,&GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate=BaudRate;
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件流控
USART_InitStructure.USART_Mode=USART_Mode_Tx;//引脚初始化为发送模式
USART_InitStructure.USART_Parity=USART_Parity_No;//无奇偶校验
USART_InitStructure.USART_StopBits=USART_StopBits_1;//停止位为1位
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长位8bit即没有校验位
USART_Init(USART1,&USART_InitStructure);
USART_Cmd(USART1,ENABLE);//USART硬件使能
}
2.写发送函数
1.发送一个字节
每次对DR寄存器的写操作会清空TXE标志位,故不需要手动清除。
void Serial_SendByte(uint8_t data)
{
USART_SendData(USART1,data);//通过DR寄存器发送一个字节
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//等待TDR位空再发送下一个字节的数据,TDR的写命令会自动清除TXE标志位
}
2.发送一个数组
void Serial_SendArry(uint8_t *arry,uint8_t length)
{
for(int i=0;i<length;i++)
{
Serial_SendByte(arry[i]);
}
}
3.发送一个字符串
void Serial_String(char* String)
{
for(int i =0;String[i]!=0;i++)
{
Serial_SendByte(String[i]);
}
}
4.发送数字
void Serial_SendNum(uint16_t Num)
{
uint16_t weishu=1+log10(Num);
uint8_t data=0;
uint16_t chushu=0;
for(int i = weishu-1;i>=0;i--)
{
chushu=(uint16_t) pow(10,i );
data=Num/chushu;
Num=Num%chushu;
Serial_SendByte(data+0x30);
}
}
5.printf重定向
这里需要注意,需要在魔术棒中勾上相关选项
//重写fputc函数
int fputc(int ch, FILE *f)
{
Serial_SendByte(ch);
return ch;
}
二、串口接收
1.轮询方式接收数据
即在主循环中不断查询DR寄存器中的RXNE标志位是否被置为,若被置位,则说明有数据被接收,此时便可以使用USART_ReceiveData()函数去取数据。同样,对DR寄存器的读操作也会被清零。故不需要手动清零。
while(1)
{
if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==SET)
{
data=USART_ReceiveData(USART1);
printf("data=%d\r\n",data);
}
}
2.中断方式接收数据
1.在初始化中加入与中断相关的函数
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
NVIC_InitTypeDef usart_InitStructure;
usart_InitStructure.NVIC_IRQChannel=USART1_IRQn;
usart_InitStructure.NVIC_IRQChannelCmd=ENABLE;
usart_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
usart_InitStructure.NVIC_IRQChannelSubPriority=2;
NVIC_Init(&usart_InitStructure);
2.写中断函数以及相关接口函数
uint8_t Serial_GetFlag(void)
{
if(Rxflag==1)
{
Rxflag=0;
return 1;
}
else
return 0;
}
uint8_t Serial_GetData(void)
{
return Rxdata;
}
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
{
Rxdata=USART_ReceiveData(USART1);
Rxflag=1;
}
}
3.主函数
while(1)
{
if(Serial_GetFlag()==1)
{
printf("data=%d\r\n",Serial_GetData());
}
}
}
4.或者直接在中断中输出也可以
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
{
printf("rxdata=%d\r\n",USART_ReceiveData(USART1));
}
}
3.串口接收HEX数据包
原理就是使用状态机的方式
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
{
static uint8_t status=0;
static uint8_t PacketNum=0;
if(status==0)
{
if(USART_ReceiveData(USART1)==0XFF)//如果接收到了包头OXFF,则进入下一个状态
{
status=1;
}
}
else if(status==1)//不断接受数据包的内容,如果接收了四个,则进入下一个状态
{
if(PacketNum<4)
{
Rxdata[PacketNum]=USART_ReceiveData(USART1);
PacketNum++;
}
else
status=2;
}
else if(status==2)//如果接收到了OXFE,则说明接收到了包尾,则将状态位以及数组个数全部清零,同时至标志位为1,允许主循环检测
{
if(USART_ReceiveData(USART1)==0xFE)
{
status=0;
PacketNum=0;
Rxflag=1;
}
}
}
}
while(1)
{
if(Serial_GetFlag()==1)
{
for(int i =0;i<4;i++)
{
printf("Rxdata的值为[%d]=:%d\r\n",i,Rxdata[i]);
}
}
}
}
4.串口接收文本数据包
char Rxdata[100] ;
uint8_t Rxflag;
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
{
static uint8_t status=0;
static uint8_t PacketNum=0;
if(status==0)
{
if(USART_ReceiveData(USART1)=='@')
{
status=1;
}
}
else if(status==1)
{
if(USART_ReceiveData(USART1)!='\r')
{
Rxdata[PacketNum]=USART_ReceiveData(USART1);
PacketNum++;
}
else
status=2;
}
else if(status==2)
{
if(USART_ReceiveData(USART1)=='\n')
{
Rxdata[PacketNum]=0;//这里加上'\0',是字符串结束的标志
status=0;
PacketNum=0;
Rxflag=1;
}
}
}
}
while(1)
{
if(Serial_GetFlag()==1)
{
Serial_String(Rxdata);
Serial_SendByte('\r');
Serial_SendByte('\n');
}
}