极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 13005|回复: 5

求教串口接收长字符串的方法?

[复制链接]
发表于 2014-3-18 22:40:37 | 显示全部楼层 |阅读模式
本帖最后由 hi55234 于 2014-3-23 20:27 编辑

available()

Get the number of bytes (characters) available for reading from the serial port. This is data that's already arrived and stored in the serial receive buffer (which holds 64 bytes). available() inherits from the Stream utility class.


while (Serial.available() > 0) {  

temp1[jsq1]=Serial.read();

}

因为Serial.available() 撑死等于64,在接收长字符串的时候就出现了困难

比如,接收GPS信号的$GPGGA,一般来说这一行就是75个字符

当除开关键字“$GPGGA”,能取得的就只剩下57个字符(缓冲区共64个字符,最后一个还是空的),那么缓冲区外的字符如何取得?(使用Serial.read() 拾取缓冲区内的数据后,缓冲区内数据减少了,缓冲区外数据貌似也没继续缓冲(至少Serial.available()没有计算新缓冲的字符 ))

------------------------------------------------
能否接受完整的长字符串,重点在于波特率与延时的配合~~~

用微妙去细调延时,远比毫秒来得靠谱

例如,以9600波特率为例,发送一字节需要1毫秒,那么1300微秒的延时就完爆2000微秒,后者会在140字节后开始丢数据~~

顺便说一下,最后GPS数据不完整,不是因为gps有问题,而是因为延时不对,而完整的GPS数据,不输出$GPGLL、$GPVTG、$GPGSV仅3组(可见卫星最多12)的情况下,整个字符串也在380左右,换言之,在此情况下,数组设为450为宜,而比较完整的数据(4组$GPGSV,输出$GPGLL、$GPVTG),整个数组需要600字节,以SRAM 1 KB (ATmega328)计算,真心有点伤不起
回复

使用道具 举报

 楼主| 发表于 2014-3-20 16:43:50 | 显示全部楼层
本帖最后由 hi55234 于 2014-3-20 16:46 编辑

gps程序1


  1. char temp1[80],temp2[80];

  2. int jsq1=0;
  3. int timetest1,timetest2,timetest3,timetest4;


  4. boolean change1=1;

  5. int panduan1,panduan2,panduan3,panduan4;
  6. boolean GPGGAget=0;
  7. boolean GPRMCget=0;

  8. void setup() {
  9.    Serial.begin(9600);
  10. }


  11. void loop() {

  12. panduan1=0;
  13. panduan2=0;
  14. panduan3=0;
  15. panduan4=0;

  16. timetest1=1;
  17. timetest2=1;
  18. timetest3=1;
  19. timetest4=1;

  20. jsq1=0;

  21. while (Serial.available() > 0) {  
  22.   
  23. temp1[jsq1] = Serial.read();
  24. delay(2);
  25. if(!GPGGAget){
  26. temp2[jsq1] = temp1[jsq1];
  27. delay(2);
  28. }


  29. if(jsq1>2){

  30. if(temp1[jsq1-2]=='G' && temp1[jsq1-1]=='G')panduan1=1;
  31. if(panduan1 && temp1[jsq1]=='A')panduan2=1;
  32. else panduan1=0;

  33. if(temp1[jsq1-2]=='R' && temp1[jsq1-1]=='M')panduan3=1;
  34. if(panduan3 && temp1[jsq1]=='C')panduan4=1;
  35. else panduan3=0;
  36. }

  37. jsq1++;

  38. }


  39. if(panduan2){
  40. Serial.println("find $GPGGA");
  41. GPGGAget=1;
  42. }

  43. if(panduan4){
  44. Serial.println("find $GPRMC");
  45. GPRMCget=1;
  46. }

  47. if(GPGGAget && GPRMCget){
  48. GPGGAget=0;
  49. GPRMCget=0;

  50. if(temp2[45]>0 && temp1[18]=='A'){ //数据有效性判断,GGA非0,RMC为A

  51. //time test
  52. for(int col=7;col<17;col++){
  53. if(temp2[col]==temp1[col]) timetest1=1;
  54. else timetest1=0;
  55. timetest2=timetest2*timetest1;
  56. }

  57. //维度/经度 test
  58. for(int col=18;col<44;col++){
  59. if(temp2[col]==temp1[col+2]) timetest3=1;
  60. else timetest3=0;
  61. timetest4=timetest4*timetest3;
  62. }

  63. if(timetest2)Serial.println("time OK");
  64. else Serial.println("time error");

  65. if(timetest4)Serial.println("jingduweidu OK");
  66. else Serial.println("jingduweidu error");

  67. }else Serial.println("weidingwei error");


  68. }



  69. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2014-3-21 10:41:27 | 显示全部楼层
string str += Serial.read();
这样?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-21 15:08:20 | 显示全部楼层
本帖最后由 hi55234 于 2014-3-23 20:09 编辑
麽麽茶㊣ 发表于 2014-3-21 10:41
string str += Serial.read();
这样?


string 作为 str 的定义,在最开始用了,就ok了

-----------------------------------------------------------------
现实与想象有差异~~~

用检测程序:

  1. char temp1[500],temp2[80];

  2. int jsq1=0;
  3. int timetest1,timetest2,timetest3,timetest4;


  4. boolean change1=0;

  5. int panduan1,panduan2,panduan3,panduan4;
  6. boolean GPGGAget=0;
  7. boolean GPRMCget=0;

  8. void setup() {
  9.    Serial.begin(9600);
  10. }


  11. void loop() {

  12. panduan1=0;
  13. panduan2=0;
  14. panduan3=0;
  15. panduan4=0;

  16. timetest1=1;
  17. timetest2=1;
  18. timetest3=1;
  19. timetest4=1;

  20. jsq1=0;

  21. while (Serial.available() > 0) {  
  22.   
  23. temp1[jsq1] = Serial.read();
  24. delay(2);

  25. jsq1++;
  26. change1=1;
  27. }

  28. if(change1){
  29.   
  30. Serial.println("--------------------------------------------------");
  31. Serial.print(temp1);
  32. Serial.println("--------------------------------------------------");

  33. for(int col=0;col<500;col++)temp1[col]=0;
  34. }
  35. change1=0;

  36. }
复制代码



输出打印为:
  1. --------------------------------------------------

  2. $GPGGA,065540.248,2934.7910,N,10631.5621,E,0,00,,,M,,,,0000*04

  3. $GPGSA,A,1,,,,,,,,,,,,,,,*1E

  4. $GPGSV,1,1,00*79

  5. $GPRMC,065540.248,V,2934.7910,N,163.61,,,131,*B
  6. --------------------------------------------------

  7. --------------------------------------------------

  8. $GPGGA,065541.241,2934.7910,N,10631.5621,E,0,00,,,M,,,,0000*0C

  9. $GPGSA,A,1,,,,,,,,,,,,,,,*1E

  10. $GPGSV,1,1,00*79

  11. $GPRMC,065541.241,V,2934.7910,N,163.61,,,131,*3
  12. --------------------------------------------------

  13. --------------------------------------------------

  14. $GPGGA,065542.241,2934.7910,N,10631.5621,E,0,00,,,M,,,,0000*0F

  15. $GPGSA,A,1,,,,,,,,,,,,,,,*1E

  16. $GPGSV,1,1,00*79

  17. $GPRMC,065542.241,V,2934.7910,N,163.61,,,131,*0
  18. --------------------------------------------------

  19. --------------------------------------------------
复制代码



数据一次性打印出来···········,并非为想象中的分别打印出来

PS:上次打印不全,估计是数组当初设置小了

另外,输出项目,少了不少项目,需要重新设置输出

办公室信号极限:
  1. --------------------------------------------------

  2. --------------------------------------------------

  3. --------------------------------------------------

  4. $GPGGA,085940.563,2934.7829,N,10631.6477,E,0,03,,275.0,M,,,,0000*2C

  5. $GPGSA,A,1,20,16,32,,,,,,,,,,,,*1A

  6. $GPGSV,3,1,11,16,62,235,22,32,39,223,32,0,020,21,1,3,7A
  7. GGS,,,1,14,05,3,738172,1,7,291,4,*8
  8. GPS,,31,31219,1,506,0,3,9,4F
  9. GRM,890.6,,23.82,,03167,E,2034,1

  10. --------------------------------------------------
复制代码



回复 支持 反对

使用道具 举报

发表于 2014-3-25 16:34:44 | 显示全部楼层
如果不是一直发的信号。不用char数组啊。
Serial.read()收的就是char  赋值给string进行累加。全部收完后。就是一个你要的字符串了。

除非像点位机一样,不停的发送的。。那只能靠你这种了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-25 16:53:20 | 显示全部楼层
麽麽茶㊣ 发表于 2014-3-25 16:34
如果不是一直发的信号。不用char数组啊。
Serial.read()收的就是char  赋值给string进行累加。全部收完后。 ...

做成char 数组,主要是一开始就可以限定数组的大小,而不需要自定义~~~

至于gps数据,10组gps数据,就是610字节,内存真心伤不起~~~

后期优化,目测需要在接收过程中进行判断·······

否则1k小内存,伤不起啊伤不起~~~
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-5 15:15 , Processed in 0.038075 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表