环境设置:
stc8a8k;
波特率115200;
晶振22.1184Mhz;
定时器2产生波特率;
代码例子
发送数据到电脑中,用printf函数;
将电脑发过来的字符串,按照指定格式,截取出数据;
将电脑发过来的字符串,按照指定命令,判断命令;
超时判断接收的思路。。
截取整数,
截取小数,
截取几个数,数组
//@22.1184M,stc8a8k
#include <stc8a8k.h>
#include <LCD12864B.h>
#include <delay.h>
#include <stdio.h>
#include "stdlib.h"
#include "stdarg.h"
#include "string.h" //str函数
//****************************************************************
#define Uart1_Rec_Maxlength 100
unsigned char Global_Uart1_Rec[Uart1_Rec_Maxlength];//串口1接收空间,100个字节
#define Uart1_END_CODE '#' //帧尾自定义符号
unsigned char Uart1_Rec_Byte_Length=0;//动态长度,在0-最大Uart1_Rec_Maxlength=100之间
unsigned char Uart1_Rec_Frame_Flag=0;//接收一帧标记,=1,接收到一帧数据,=0,没有接受一帧数据
unsigned Global_uart1cmdnum=0;//串口接收到的命令号
#define Uart1CMD_NULL 0 //串口接收到的命令
#define Uart1CMD_LED0 1 //串口接收到的命令
#define Uart1CMD_LED1 2 //串口接收到的命令
#define Uart1CMD_LED2 3 //串口接收到的命令
//************************
void UartInit(void); //115200bps@11.0592MHz
void UART1_SendData(char dat);
void UartSendStr(char *p);
void Clear_Uart1_Rxbuff(void);
unsigned char Judge_Uart1_Response(char* fmt,...);
unsigned char Get_Uart1_AngleData(float *input_angle);
unsigned char Get_Uart1_Int_Data(int *input_data);
unsigned char Get_Uart1_Many(int input_data[]);
void printf_char_int_long_test(void);
void printf_float_test(void);
void printf_String_test(void);
//*******************************主函数************************
int main()
{
float angle_x=0;
int xmm;
int input_dataRec[3];
int i,j;
UartInit();//串口1,波特率115200,定时器2产生,stc8a8k,22.1184Mhz
ES = 1;
EA = 1;
//LCD12864_Init(); //初始化LCD
//LCD12864_Clr_Scr();//清屏函数
//LCD12864_Write_string(2, 3 ,"welcome");
// delay_ms(1000);
//LCD12864_Clr_Scr();//清屏函数
printf("LED=0\r\n");//给串口电脑发送,反应一下。
printf_char_int_long_test();
printf_float_test();
printf_String_test();
while(1)
{
if(Global_uart1cmdnum==Uart1CMD_LED0) //获取浮点数
{
Global_uart1cmdnum=Uart1CMD_NULL;//清空命令,防止重复响应
printf("Uart1CMD_LED0 \r\n");
printf("angle cal");
i=0;
while(!Get_Uart1_AngleData(&angle_x))// //电脑发过来的格式 angle_x=数据,超时监控
{
delay_ms(5);
i++;
if(i>3000)return 0;//超时监控
}
angle_x=angle_x+100;
printf("angle_x=%.2f\r\n",angle_x);
}
else if(Global_uart1cmdnum==Uart1CMD_LED1)//超时监控
{
Global_uart1cmdnum=Uart1CMD_NULL;//清空命令,防止重复响应
printf("Uart1CMD_LED1 \r\n");
printf("xmm rec \r\n");
i=0;
while(! Get_Uart1_Int_Data(&xmm))//电脑发过来的格式 xmm=数据 ,超时监控
{
delay_ms(5);
i++;
if(i>3000)return 0;//超时监控
}
xmm=xmm+100;
printf("xmm=%d\r\n",xmm);
}
else if(Global_uart1cmdnum==Uart1CMD_LED2)
{
Global_uart1cmdnum=Uart1CMD_NULL;//清空命令,防止重复响应
printf("Uart1CMD_LED2\r\n");
printf("input_dataRec rec \r\n");
i=0;
while(!Get_Uart1_Many(input_dataRec))//电脑发过来的格式lr:数据,ud:数据,an:数据,超时监控
{
delay_ms(5);
i++;
if(i>3000)return 0;//超时监控
}
printf("input_dataRec[0]=%d\r\n",input_dataRec[0]); // LED=2#
printf("input_dataRec[1]=%d\r\n",input_dataRec[1]); //
printf("input_dataRec[2]=%d\r\n",input_dataRec[2]); //
}
}
}
//串口1,波特率115200,定时器2产生,
void UartInit(void) //115200bps@22.1184Mhz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR &= 0xFB; //定时器2时钟为Fosc/12,即12T
T2L = 0xFC; //设定定时初值
T2H = 0xFF; //设定定时初值
AUXR |= 0x10; //启动定时器2
}
//UART1 发送串口数据,一个字节
void UART1_SendData(char dat)
{
ES=0; //关串口中断
SBUF=dat;
while(TI!=1); //等待发送成功
TI=0; //清除发送中断标志
ES=1; //开串口中断
}
//UART1 发送串口数据,字符串
void UartSendStr(char *p)
{
while (*p)
{
UART1_SendData(*p++);
}
}
//重写putchar函数,可以用printf函数
char putchar(char c)
{
UART1_SendData(c);
return c;
}
//串口1中断服务函数
void Uart1Isr() interrupt 4 using 1
{
unsigned char cmdtemp=0;
if (TI)
{
TI = 0;
}
if (RI)
{
Global_Uart1_Rec[Uart1_Rec_Byte_Length]=SBUF;//将数据放到缓冲区中
// UART1_SendData(SBUF);//debug,给串口电脑发送,反应一下。
// printf("\r\n");//debug给串口电脑发送,反应一下。
if(Global_Uart1_Rec[Uart1_Rec_Byte_Length]==Uart1_END_CODE) //如果接收到的最后的数据是约定好的帧尾
{
Uart1_Rec_Byte_Length=0;//接收标记等于1,在哪里清0?在判断里面清0
Uart1_Rec_Frame_Flag=1;//长度清零,给下次使用
//判断命令,得到串口命令
if(Judge_Uart1_Response("LED=0"))//如果一帧数据里面包括了LED=0
{
Clear_Uart1_Rxbuff(); //清空空间,下次接收
Global_uart1cmdnum = Uart1CMD_LED0;
}
else if(Judge_Uart1_Response("LED=1"))//如果一帧数据里面包括了LED=0
{
Clear_Uart1_Rxbuff(); //清空空间,下次接收
Global_uart1cmdnum = Uart1CMD_LED1 ;
}
else if(Judge_Uart1_Response("LED=2"))//如果一帧数据里面包括了LED=0
{
Clear_Uart1_Rxbuff(); //清空空间,下次接收
Global_uart1cmdnum = Uart1CMD_LED2 ;
}
}
else
{
Uart1_Rec_Byte_Length++;//递增,不断放到数组中
if(Uart1_Rec_Byte_Length>Uart1_Rec_Maxlength-1) Uart1_Rec_Byte_Length=0;
}
RI = 0;
}
}
//清除串口1的内存
void Clear_Uart1_Rxbuff(void)
{
unsigned char *p,i;
p=Global_Uart1_Rec;
for(i=0;i<Uart1_Rec_Maxlength;i++)
{
*p++=0;
}
Uart1_Rec_Byte_Length=0;
Uart1_Rec_Frame_Flag=0;
}
//判断命令,这里注意,必须全部包括
unsigned char Judge_Uart1_Response(char* fmt,...)
{
va_list ap;
char p[30];
if(!Uart1_Rec_Frame_Flag) return 0;
va_start(ap,fmt);
vsprintf((char*)p,fmt,ap);
va_end(ap);
if(strstr((char*)Global_Uart1_Rec,p)==NULL) return 0;
else return 1;
}
//实例,获取串口传来的角度,angle=325.56
unsigned char Get_Uart1_AngleData(float *input_angle)
{
float angletemp;
if(!Uart1_Rec_Frame_Flag) return 0;
sscanf((const char *)Global_Uart1_Rec,"angle_x=%f",&angletemp);//angle=325.56
*input_angle=(float)angletemp;
return 1;
}
//实例,获取串口传来的整数,intdata=13568
unsigned char Get_Uart1_Int_Data(int *input_data)
{
int inttemp;
if(!Uart1_Rec_Frame_Flag) return 0;
sscanf((const char *)Global_Uart1_Rec,"xmm=%d",&inttemp);//xmm=8756
*input_data=(float)inttemp;
return 1;
}
//接收一系列,截取出来数据lr:%d,ud:%d,an:%d
unsigned char Get_Uart1_Many(int input_data[])
{
int input_dataTemp[3];
if(!Uart1_Rec_Frame_Flag) return 0;
sscanf((const char *)Global_Uart1_Rec,"lr:%d,ud:%d,an:%d",&input_dataTemp[0],&input_dataTemp[1],&input_dataTemp[2]);
input_data[0]=input_dataTemp[0];
input_data[1]=input_dataTemp[1];
input_data[2]=input_dataTemp[2];
return 1;
}
//测试给串口发送字符,整数和长整数
void printf_char_int_long_test(void)
{
char a=-100;
int b=-2000;
long c=6553600;
printf ("char %bd int %d long %ld\r\n",a,b,c); // 10进制输出
// 输出带符号10进制整数(正数不输出符号)
// 实际输出:char -100 int -2000 long 6553600
printf ("char_0x%bx int_0x%x long_0x%lx\r\n",a,b,c); // 16进制输出
// 输出无符号16进制整数,x表示按小写输出,X表示按大写输出
// 实际输出:char_0x9c int_0xf830 long_0x640000
printf ("a_int %d\r\n",(int)(a)); // 不用宽度标识符
// 实际输出:a_int -100
printf ("char %bd,int %d,long %ld\r\n",a,b,c); // %bd后也可以有其它普通字符
// 输出带符号10进制整数(正数不输出符号)
// 实际输出:char -100,int -2000,long 6553600
}
//测试发送浮点数到串口
void printf_float_test(void)
{
float a= 3.14159265798932;
float f = 10.0,g = 22.95;
printf("Max is %f\r\n",a); // Max is 3.141593, 默认小数点后6位
printf("%.4f\r\n",a); // 3.1416
printf("%.12f\r\n",a); // 3.140593000000
//%.4f 表示按小数点后4 位数据输出,%.12f表示按小数点后12位数据输出
printf ("%f , %g\r\n", f, g); //输出:10.000000 , 22.95
}
//测试发送字符串
void printf_String_test(void)
{
char buf [] = "Test String";
char *p = buf;
printf ("String %s is at address %p\r\n",buf,p);
//输出:String Test String is at address i:0022
}