串口收到字符后进行转换

五行外的小和尚 2013-12-09 05:55:55
如果串口收到收据,如何进行格式转换?
如我想把每个数据都转成对应的16进制ascii,并且转完后,以固定格式发送出去,比如a,就是AT%IPSEND="61",比如b,就是AT%IPSEND="62",ab就是AT%IPSEND="6162"
下面是教科书上的程序:
#include <reg52.h>
#define uchar unsigned char ;
bit Flag; //串口接收到字符的标志
unsigned char UartChar;


/*--------------------------------------------------------------
函数声明
--------------------------------------------------------------*/
void InitUART(void);
void SendByte(unsigned char dat);
void SendStr(unsigned char *s);

/*--------------------------------------------------------------
主函数
--------------------------------------------------------------*/
void main (void)
{
//串口初始化
InitUART();

SendStr("\r\n\n SZ-51 UART test OK if you see these words!");
SendStr("\r\n ARM技术论坛 神舟51开发板 单片机串口收发测试");
SendStr("\r\n 神舟51开发板,中断方式接收,请输入字符:");

Flag = 0;
while (1)
{
if(Flag == 1)
{
Flag = 0;
SendByte(UartChar);
if(UartChar == '\r')
{
SendByte('\n');
}
}
}
}

/*--------------------------------------------------------------
串口初始化
--------------------------------------------------------------*/
void InitUART(void)
{

SCON = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收
TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit 重装
//TH1 = 0xF3; // 波特率4800、数据位8、停止位1。效验位无 (12M)
TH1 = 0xFD; // TH1: 重装值 9600 波特率 晶振 11.0592MHz
TR1 = 1; // TR1: timer 1 打开
EA = 1; //打开总中断
ES = 1; //打开串口中断
}

/*--------------------------------------------------------------
发送一个字节
--------------------------------------------------------------*/
void SendByte(unsigned char dat)
{
SBUF = dat;
while(!TI);
TI = 0;
}

/*--------------------------------------------------------------
发送一个字符串
--------------------------------------------------------------*/
void SendStr(unsigned char *s)
{
//检测是否字符串末尾, '\0'表示字符串结束标志,
while(*s != '\0')
{
SendByte(*s);
s++;
}
}

/*--------------------------------------------------------------
串口中断程序
--------------------------------------------------------------*/
void UART_SER (void) interrupt 4 //串行中断服务程序
{
if(RI) //判断是接收中断产生
{
RI=0; //标志位清零
UartChar = SBUF; //读入缓冲区的值
Flag = 1; //把值输出到P1口,用于观察
}

if(TI) //如果是发送标志位,清零
{
//TI=0; //发送为查询方式
}
}


串口中断接收到的数据都是一个字符一个字符的往回传的,中断通过收SBUF传给UartChar,UartChar再传给发的SBUF,然后就发出去了。
我现在想转换,但是UartChar进行操作,我是这么操作的,
uchar buf3[4],buffer[]="AT%IPSEND=\"",*buf4,buf1[32];
buf3[0]=UartChar;
buf4=buffer;
SendStr(buf3);
hextodstr(buf3);
strcat(buf3,"\"\n\r");
SendStr(buf3);
strcat(buf4,buf3);
SendStr(buf4);
uchar *hextodstr(uchar * src)
{
uchar i=0;
while(*src!=0)
{
buf1[2*i]=*src/16+'0';
buf1[2*i+1]=(*src%16)+'0';
src++;
i++;
if(i>=16)
{
//缓冲区不够
buf1[32]=0;
// return buf1;
}
}
buf1[i*2]=0;//忘记给字符串补结束符了
return buf1;
}
这样做以后,我用DEBUG模式调试,也看不出来什么异常。while循环内我用的静态变量,那个几个buf都是静态的,这样下次调用就不会被累加了,但是结果是错误的。
...全文
733 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
引用 6 楼 li880wert 的回复:
sprintf 可以,用sprintf 打印sql语句的 增,删,改,查比你这格式复杂多了,记得加转义字符就行了
嗯嗯嗯,转换函数都是对的 今天我早上又试验了一次,我发现是中断的问题 #include <reg52.h> #define uchar unsigned char ; bit Flag; //串口接收到字符的标志 unsigned char UartChar; /*-------------------------------------------------------------- 函数声明 --------------------------------------------------------------*/ void InitUART(void); void SendByte(unsigned char dat); void SendStr(unsigned char *s); /*-------------------------------------------------------------- 主函数 --------------------------------------------------------------*/ void main (void) { //串口初始化 InitUART(); SendStr("\r\n\n SZ-51 UART test OK if you see these words!"); SendStr("\r\n ARM技术论坛 神舟51开发板 单片机串口收发测试"); SendStr("\r\n 神舟51开发板,中断方式接收,请输入字符:"); Flag = 0; while (1) { if(Flag == 1) { Flag = 0; SendByte(UartChar); if(UartChar == '\r') { SendByte('\n'); } } } } /*-------------------------------------------------------------- 串口初始化 --------------------------------------------------------------*/ void InitUART(void) { SCON = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收 TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit 重装 //TH1 = 0xF3; // 波特率4800、数据位8、停止位1。效验位无 (12M) TH1 = 0xFD; // TH1: 重装值 9600 波特率 晶振 11.0592MHz TR1 = 1; // TR1: timer 1 打开 EA = 1; //打开总中断 ES = 1; //打开串口中断 } /*-------------------------------------------------------------- 发送一个字节 --------------------------------------------------------------*/ void SendByte(unsigned char dat) { SBUF = dat; while(!TI); TI = 0; } /*-------------------------------------------------------------- 发送一个字符串 --------------------------------------------------------------*/ void SendStr(unsigned char *s) { //检测是否字符串末尾, '\0'表示字符串结束标志, while(*s != '\0') { SendByte(*s); s++; } } /*-------------------------------------------------------------- 串口中断程序 --------------------------------------------------------------*/ void UART_SER (void) interrupt 4 //串行中断服务程序 { if(RI) //判断是接收中断产生 { RI=0; //标志位清零 UartChar = SBUF; //读入缓冲区的值 Flag = 1; //把值输出到P1口,用于观察 } if(TI) //如果是发送标志位,清零 { //TI=0; //发送为查询方式 } } 这个是我买单片机是书上带的教程。 因为我的函数需要转换,我一直没有找出问题在哪里。 今天早上我是这么试的,我把while循环的地方改了 while (1) { if(Flag == 1) { Flag = 0; SendByte('a'); } 当我发送数据的时候,发送几个数据就会中断几次,出现几个a 我又这么试 while (1) { if(Flag == 1) { Flag = 0; SendStr("abcdef"); } 然后就会出现当我发送数据的多少决定了输出多少个“abcdef”,1-1,2-1,3-2,4-2,5-2,6-2 所以我觉得应该是这个发送字符串这里执行的机器周期多了,所以导致中断次数少了。 导致数据丢失了。
libai 2013-12-10
  • 打赏
  • 举报
回复
sprintf 可以,用sprintf 打印sql语句的 增,删,改,查比你这格式复杂多了,记得加转义字符就行了
schlafenhamster 2013-12-10
  • 打赏
  • 举报
回复
通常发送 是 不使用 中断的, 因为 何时要发送 你是 知道的,如果 使用 中断, 有时 会 发生 中断 丢失,(以后的 东西 就 发不出去了)。
  • 打赏
  • 举报
回复
引用 3 楼 pathletboy 的回复:
void trans(char* buff, char* str)
{
#define STR_HEAD "AT%IPSEND=\""
#define HEAD_SIZE sizeof(STR_HEAD)-1
	memcpy(buff, STR_HEAD, HEAD_SIZE);
	buff+=HEAD_SIZE;
	while (*str)
	{
		sprintf(buff,"%.2x", *str);
		buff+=2;
		str++;
	}
	*buff++ = '\"';
	*buff = 0;
}
http://ideone.com/7hTHCz
版主以前帮我写过一个16进制转10进制的函数,现在的问题是如果正常收发字符是正常的 uchar *hextodstr(uchar * src) { uchar i=0; while(*src!=0) { buf1[2*i]=*src/16+'0'; buf1[2*i+1]=(*src%16)+'0'; src++; i++; if(i>=16) { //缓冲区不够 buf1[32]=0; // return buf1; } } buf1[i*2]=0;//忘记给字符串补结束符了 return buf1; } 我如果调用这个函数,就会出现死机或者什么的,我是这么调用的 串口给我送回的是UartChar,我如果把收到的字符累加,就会死机! uchar buf3[4],buffer[]="AT%IPSEND=\"",*buf4,buf1[32]; buf3[0]=UartChar; buf4=buffer; SendStr(buf3); hextodstr(buf3); strcat(buf3,"\"\n\r"); SendStr(buf3); strcat(buf4,buf3); SendStr(buf4); 你的函数比上面的函数更直接,就是直接到我需要的了,但是那边给我返回的是一个字符,这个函数我不知道能不能对字符操作。当我把字符放进数组,然后把数组带劲转换函数,就会出现乱码的。
Mr. Code 2013-12-09
  • 打赏
  • 举报
回复
错误较多
引用
uchar buf3[4],buffer[]="AT%IPSEND=\"",*buf4,buf1[32]; buf3[0]=UartChar; buf4=buffer; SendStr(buf3); // buf[3]只给[0]置了UartChar,后面的都是随机数,是否该给[1]=0 hextodstr(buf3); strcat(buf3,"\"\n\r"); // 比如buf3[0]='a',就算buf3[1]=0,这个拼接了"\n\r三个字符后buf3[4] // 长度不够,没法放最后的结束0 SendStr(buf3); strcat(buf4,buf3); // 同样的buf4在第一条语句中被你指向了buffer,而buffer // 在你定义时就初始化给了固定的大小,哪里还能strcat? SendStr(buf4); uchar *hextodstr(uchar * src) { uchar i=0; while(*src!=0) { buf1[2*i]=*src/16+'0'; buf1[2*i+1]=(*src%16)+'0'; src++; i++; if(i>=16) { //缓冲区不够 buf1[32]=0; // buf1定义的大小就是32,下标从 0-31 , [32]明显越界 // return buf1; } } buf1[i*2]=0;//忘记给字符串补结束符了 return buf1; }
最后,给你一段代码参考:
uchar buf1[32], buf3[16];  // 根据你自己的长度设置
uchar ucChar[] = "A1&b";  // 这个例子有大小写字母和数字以及特殊符号
strcpy(buf1, "AT%IPSEND=\"");
sprintf(buf3, "%02x%02x%02x%02x", ucChar[0], ucChar[1], ucChar[2], ucChar[3]);
strcat(buf1, buf3);
strcat(buf1, "\"");
最后得到的buf1就是AT%IPSEND="41312662",包括双引号,是你要的结果。
pathletboy 2013-12-09
  • 打赏
  • 举报
回复
void trans(char* buff, char* str)
{
#define STR_HEAD "AT%IPSEND=\""
#define HEAD_SIZE sizeof(STR_HEAD)-1
	memcpy(buff, STR_HEAD, HEAD_SIZE);
	buff+=HEAD_SIZE;
	while (*str)
	{
		sprintf(buff,"%.2x", *str);
		buff+=2;
		str++;
	}
	*buff++ = '\"';
	*buff = 0;
}
http://ideone.com/7hTHCz
  • 打赏
  • 举报
回复
引用 1 楼 li880wert 的回复:
用sprintf 最简单了
sprintf只是输出,但是我要的确是AT%IPSEND="",双引号里面的内容才是我需要转的,但是我需要发送给下位机的却是全部的 AT%IPSEND="",这么个意思,我需要发送的是abc,我就必须得以AT%IPSEND="616263",如果我需要发送123456,我就必须发送AT%IPSEND="3132333435",sprintf怎么能输出这样的格式呢?
libai 2013-12-09
  • 打赏
  • 举报
回复
用sprintf 最简单了

27,377

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧