STM32串口通信代码、ASCII码、XU4串口通信,printf只会转换为无符号类型,linux下的串口通信程序
2016-11-16 15:48
1016 查看
1、其里面的的通信协议是是自己定的,这里 是检测到数据的结尾是以0x0d、0x0a结尾,则表示接受的数据完成了,这个数据是我想要的,这样子就不会出现一些错乱的数据信息。其中的0x8000、0x4000只是一个标志位来的。
a、这里的数据加的0d、0a分别是回车、换行的十六进制,当我们编写程序的时候需要在数据的结尾加上这两个十六进制,否则接受端会以接受不到这两个数据,而丢弃所接受的数据。
b、其中ASCII跟十六进制的关系 ,其中ASCII码就是字符
关于这张表,主要是键盘上的键值字符在计算机中的二进制存储,为了方便,转化成的16进制表示。
所以,45的ASCII表示就是4的ASCII表示和5的ASCII表示联结起来的。
每个ASCII字符转化成16进制是两位的16进制数,即一个字节,同样,把16进制数转化成ASCII时是两位一起转化成一个ASCII字符,然后把他们联结起来。
注意:计算机串口通信都是以二进制的0、1来进行通信的,我们所说的发送字符即也是ASCII码、数值。其发送是转换成二进制,而二进制一般是从十六进制转换来的,所以,这两都需转换为十六进制,然后变为二进制进行传输,而在接收端,则是把这些接收到的二进制进行解析,这需要根据协议来进行解析的,例如
传送端发送ASCII码为:a字符
计算机传输时先转为:61H 然后变为:0110 0001 最后进行传输
接收端定义一个char型字符jj,然后jj读取,然后其在程序中就可以使用了,假如作为标志位;则
if(jj=='a')..
或者if(jj==97)..
其实jj里面存储着的是8位的二进制,就看自己怎么转换了,其中的int里存储的是32位二进制。下面就是说明这个的例如printf:
其中printf其只会转为无符号类型。例如
int Data=-2;
printf("Recv Data:%d\n",Data);
输出结果是:254
负数的反码减去2。
2、Odroid XU4与3.3v的ttl接口通信问题
a、odroid XU4的TTL口的RX、TX与3.3v芯片的TTL口RX、TX进行通信,其中XU4的RX能正确接受到3.3V芯片的TX传来的数据,但是XU4的TX无法与
芯片的RX通信,其识别不了。
b、odroid XU4的TTL口的RX、TX与PL2303串口模块的RX、TX进行通信,其能够完成双向通信,但是,有时PL2303接受到的数据会出现乱码,
解决方法:在传输的数据后面加上'\r'、'\n'这样子PL2303接受的数据就变得很正常了。
其如下:
putty显示不了中文,其是因为它这里没有中文字库,所以这里由于在ASCII码表了找不到转换,则出现乱码。一般当通讯的时候使用了中文,则其是根据中文字库转换为很多的二进制,然后在另一端再根据中文字库来解析出中文了,其是不能依靠ASCII码表来转换的。
3、linux下的串口通信程序代码:
还有读取数据后提起想要的数据时,要注意的相与是‘&’而不是‘&&’,例如:
原子哥,我是新手,最近看到串口通信那一块,那个串口中断函数那里 void USART1_IRQHandler(void) //串口1中断服务程序 { u8 Res; #ifdef OS_TICKS_PER_SEC //如果时钟节拍数定义了,说明要使用ucosII了. OSIntEnter(); #endif if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾) { Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据 if((USART_RX_STA&0x8000)==0)//接收未完成 { if(USART_RX_STA&0x4000)//接收
a、这里的数据加的0d、0a分别是回车、换行的十六进制,当我们编写程序的时候需要在数据的结尾加上这两个十六进制,否则接受端会以接受不到这两个数据,而丢弃所接受的数据。
b、其中ASCII跟十六进制的关系 ,其中ASCII码就是字符
ASCII与16进制转换 | |||||||
ASCII | 16进制 | ASCII | 16进制 | ASCII | 16进制 | ASCII | 16进制 |
NUL | 00H | DLE | 10H | SP | 20H | 0 | 30H |
SOH | 01H | DC1 | 11H | ! | 21H | 1 | 31H |
STX | 02H | DC2 | 12H | " | 22H | 2 | 32H |
ETX | 03H | DC3 | 13H | # | 23H | 3 | 33H |
EOT | 04H | DC4 | 14H | $ | 24H | 4 | 34H |
ENQ | 05H | NAK | 15H | % | 25H | 5 | 35H |
ACK | 06H | SYN | 16H | & | 26H | 6 | 36H |
BEL | 07H | ETB | 17H | ' | 27H | 7 | 37H |
BS | 08H | CAN | 18H | ( | 28H | 8 | 38H |
HT | 09H | EM | 19H | ) | 29H | 9 | 39H |
LF | 0AH | SUB | 1AH | * | 2AH | : | 3AH |
VT | 0BH | ESC | 1BH | + | 2BH | ; | 3BH |
FF | 0CH | FS | 1CH | , | 2CH | < | 3CH |
CR | 0DH | GS | 1DH | _ | 2DH | = | 3DH |
SO | 0EH | RS | 1EH | . | 2EH | > | 3EH |
SI | 0FH | US | 1FH | / | 2FH | ? | 3FH |
ASCII | 16进制 | ASCII | 16进制 | ASCII | 16进制 | ASCII | 16进制 |
@ | 40H | P | 50H | 、 | 60H | p | 70H |
A | 41H | Q | 51H | a | 61H | q | 71H |
B | 42H | R | 52H | b | 62H | r | 72H |
C | 43H | S | 53H | c | 63H | s | 73H |
D | 44H | T | 54H | d | 64H | t | 74H |
E | 45H | U | 55H | e | 65H | u | 75H |
F | 46H | V | 56H | f | 66H | v | 76H |
G | 47H | W | 57H | g | 67H | w | 77H |
H | 48H | X | 58H | h | 68H | x | 78H |
I | 49H | Y | 59H | i | 69H | y | 79H |
J | 4AH | Z | 5AH | j | 6AH | z | 7AH |
K | 4BH | [ | 5BH | k | 6BH | { | 7BH |
L | 4CH | \ | 5CH | l | 6CH | ㄧ | 7CH |
M | 4DH | ] | 5DH | m | 6DH | } | 7DH |
N | 4EH | ↑ | 5EH | n | 6EH | ~ | 7EH |
O | 4FH | ← | 5FH | o | 6FH | DEL | 7FH |
所以,45的ASCII表示就是4的ASCII表示和5的ASCII表示联结起来的。
每个ASCII字符转化成16进制是两位的16进制数,即一个字节,同样,把16进制数转化成ASCII时是两位一起转化成一个ASCII字符,然后把他们联结起来。
注意:计算机串口通信都是以二进制的0、1来进行通信的,我们所说的发送字符即也是ASCII码、数值。其发送是转换成二进制,而二进制一般是从十六进制转换来的,所以,这两都需转换为十六进制,然后变为二进制进行传输,而在接收端,则是把这些接收到的二进制进行解析,这需要根据协议来进行解析的,例如
传送端发送ASCII码为:a字符
计算机传输时先转为:61H 然后变为:0110 0001 最后进行传输
接收端定义一个char型字符jj,然后jj读取,然后其在程序中就可以使用了,假如作为标志位;则
if(jj=='a')..
或者if(jj==97)..
其实jj里面存储着的是8位的二进制,就看自己怎么转换了,其中的int里存储的是32位二进制。下面就是说明这个的例如printf:
int Data=97; nTen=write(nFd,&Data,4); nRet=read(nFd,&Data,4); printf("Recv Data:%c\n",Data); 输出的结果是:Recv Data:a 如果为printf("Recv Data:%d\n",Data); 输出的结果是:Recv Data:97还有假如我们传输的字符在这ASCII码表里没有的话,需要定义一个标准,例如汉字表,这是国家定义的标准,功能跟ASCII码表一样,如果没有这些的话,我们传输的字符显示出来是会乱码的。
其中printf其只会转为无符号类型。例如
int Data=-2;
printf("Recv Data:%d\n",Data);
输出结果是:254
负数的反码减去2。
2、Odroid XU4与3.3v的ttl接口通信问题
a、odroid XU4的TTL口的RX、TX与3.3v芯片的TTL口RX、TX进行通信,其中XU4的RX能正确接受到3.3V芯片的TX传来的数据,但是XU4的TX无法与
芯片的RX通信,其识别不了。
b、odroid XU4的TTL口的RX、TX与PL2303串口模块的RX、TX进行通信,其能够完成双向通信,但是,有时PL2303接受到的数据会出现乱码,
解决方法:在传输的数据后面加上'\r'、'\n'这样子PL2303接受的数据就变得很正常了。
其如下:
putty显示不了中文,其是因为它这里没有中文字库,所以这里由于在ASCII码表了找不到转换,则出现乱码。一般当通讯的时候使用了中文,则其是根据中文字库转换为很多的二进制,然后在另一端再根据中文字库来解析出中文了,其是不能依靠ASCII码表来转换的。
3、linux下的串口通信程序代码:
#ifndef _RECV_H #define _RECV_H #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #define BAUDRATE B115200 ///Baud rate : 115200 #define DEVICE "/dev/ttyAMA0" #define SIZE 1024 #endif #include "Recv.h" int nFd = 0; struct termios stNew; struct termios stOld; int SerialInit() { nFd = open(DEVICE, O_RDWR | O_NOCTTY | O_NDELAY); if (-1 == nFd) { perror("Open Serial Port Error!\n"); return -1; } /*这里是设置通信模式,其有阻塞、非阻塞。 当第三个设为0则是阻塞,FNDELAY为非阻塞*/ if ((fcntl(nFd, F_SETFL, 0)) < 0) { perror("Fcntl F_SETFL Error!\n"); return -1; } if (tcgetattr(nFd, &stOld) != 0) { perror("tcgetattr error!\n"); return -1; } stNew = stOld; cfmakeraw(&stNew);//将终端设置为原始模式,该模式下所有的输入数据以字节为单位被处理 //set speed cfsetispeed(&stNew, BAUDRATE);//115200 cfsetospeed(&stNew, BAUDRATE); //set databits stNew.c_cflag |= (CLOCAL | CREAD); stNew.c_cflag &= ~CSIZE; stNew.c_cflag |= CS8; //set parity stNew.c_cflag &= ~PARENB; stNew.c_iflag &= ~INPCK; //set stopbits stNew.c_cflag &= ~CSTOPB; stNew.c_cc[VTIME] = 0; //指定所要读取字符的最小数量 stNew.c_cc[VMIN] = 1; //指定读取第一个字符的等待时间,时间的单位为n*100ms //如果设置VTIME=0,则无字符输入时read()操作无限期的阻塞 tcflush(nFd, TCIFLUSH); //清空终端未完成的输入请求及数据。这个一般需要不断的放到死循环里 if (tcsetattr(nFd, TCSANOW, &stNew) != 0) { perror("tcsetattr Error!\n"); return -1; } return nFd; } int main(int argc, char **argv) { int nRet = 0; char buf[SIZE]; if (SerialInit() == -1) { perror("SerialInit Error!\n"); return -1; } bzero(buf, SIZE); while (1) { nRet = read(nFd, buf, SIZE); /*这里要不断清楚接受缓存里的数据,因为其里面可能存有很多先前的数据, 这就导致,即使没有发生数据,这里也会读到数据。*/ tcflush(nFd, TCIFLUSH); if (-1 == nRet) { perror("Read Data Error!\n"); break; } if (0 < nRet) { buf[nRet] = 0; printf("Recv Data: %s\n", buf); /*%x是十六进制,这里是以ascII码显示*/ } } close(nFd); return 0; }阻塞模式:就是read()未接受到数据则不返回,非阻塞模式:就是read()即使为接受到数据也返回。记住设置这两个模式不是通过设置VTIME、VMIN
还有读取数据后提起想要的数据时,要注意的相与是‘&’而不是‘&&’,例如:
zhentou0=Zdepth&0xff; zhentou1=Zdepth>>8&0xff; hht=Zdepth>>16&0xffff; if(zhentou0==0xeb&&zhentou1==0x90) { Zdepth=hht; }else{ Zdepth=0; }
相关文章推荐
- Linux串口接收程序会将0x0D转换成0x0A的问题记录
- Linux下基于QT的串口通信程序(Tiny6410)
- Linux 管道替换标准输入输出 实现2个独立程序代码之间的通信
- linux操作串口的代码,linux串口通信以及串口初始化代码,linux串口读写方法和代码
- 【C#串口编程计划】通信协议解析 -- byte[]与常用类型的转换
- 嵌入式linux串口通信自发自收测试程序
- Linux 下C语言学习(四)——变量的类型和程序各部分代码在内存中的位置
- linux 下串口通信程序(转载)
- linux下的串口通信程序详解
- Linux下基于QT的串口通信程序(Tiny6410)
- Linux串口通信程序
- Linux串口通信程序
- RC5编码格式的遥控器解码、PCA9633器件控制代码示例、串口通信程序示例、IIC通信示例
- STC15F2K60S2串口通信程序代码
- TCP/IP通信或串口通信数据类型转换
- java中数据类型间的最大值,最小值及转换程序代码实现
- [编写高质量代码:改善java程序的151个建议]建议65 避开基本类型数组转换列表陷阱
- Linux串口测试工具简单程序代码解析
- 在stm32 单片机程序中使用printf()进行串口调试