当前位置:   article > 正文

粤嵌实训(笔记)_粤嵌电子相册实验报告

粤嵌电子相册实验报告

目录

1. LCD换自己喜欢的颜色

 2. LCD换个图案

 3. LCD换张图片

4.网线登录

ifconfig eth0 192.168.5.9

5.触屏电子相册

6.网络编程(TCP通信)

 7.网络编程(UDP通信)

8.开发板串口通信MCU(32或Zigbee节点)

9.EDP接入onenet

10.MQTT协议接入onenet

 11.ZIGBEE发送数据,由6818开发板接收后发送到ONENET


说实话,对于这个粤嵌的实训,真的有很多想吐槽的地方,以下就是粤嵌给的一块板子,屏幕已经碎了,只有一根串口线(甚至是RS232,tm的)和一根DC电源(可能是为了省成本,要我就整个TYPEC供电了),它甚至一条MIRCOusb都不给(接OTG,后来我发现adb传输用不了,可能是这块板子OTG口需要特定的驱动,是的,我没资料),网线也没给,tftp,nfs都没法用,后面发现它竟然是用板载的一个rx工具(当时真是知识盲区),对比我用的一块全志的T113的板子,这块板子真的寄。

 吐槽完就进入正题吧,就是关于整个实训的各个实验:

1. LCD换自己喜欢的颜色

对于传输文件,我这里就统一用TFTP传输了

环境配置过程:

1.在windows环境下创建一个share文件,就用来存需要传到开发板的文件。

 2.关掉防火墙(记得把那些360之类的也关了,下面的是防火墙关闭工具)

链接:https://pan.baidu.com/s/1R5ycBw-_kbUw-jruMJyZmQ 
提取码:1234 

3.TFTP工具配置

链接:https://pan.baidu.com/s/18gele0YKJ_-J2cbJhg-QuQ 
提取码:1234 

 就改这两个,一个是share文件夹的路径,一个是本机的ip

4.把开发板IP改成与本机IP同一网段(因为我本机IP是192.168.5.10,开发板就改成192.168.5.9)

ifconfig eth0 192.168.5.9

 5.尝试ping通本机IP

6.TFTP传输

 我在share文件夹下放了一张BMP格式的图片

 tftp 192.168.5.10 -g -r func.bmp

参数的详情见这篇博客 Linux命令之tftp常用参数说明_小小小羊羊羊的博客-CSDN博客_tftp参数这玩意主要是快啊,比rx快太多了,如果你还是没配出来,那建议参考韦东山老师的配置双网卡的教程走一遍,其实我在玩粤嵌这块板子前是先去玩了T113的开发板,试着走驱动开发方向,但没办法,既然学校强制学习应用开发,那就来吧!(鸡汤)

 然后还是正题,就是显示个喜欢的颜色,很简单哈。

代码贴出来,扔到ubuntu拿交叉编译工具链跑就行

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. //ssize_t write(int fd, const void *buf, size_t count);
  7. //int open(const char *pathname, int flags);
  8. int main()
  9. {
  10. //1.打开屏幕
  11. int fd=0; //接受open的返回值
  12. fd=open("/dev/fb0", O_RDWR);
  13. if(fd==-1) //做错误判断
  14. {
  15. perror("open hello.c fail");
  16. }
  17. //2.写入颜色数据
  18. int w_ret=0;
  19. int i=0;
  20. int j=0;
  21. unsigned int color[480][800]={0};
  22. for(i=0;i<480;i++)
  23. {
  24. for(j=0;j<800;j++)
  25. {
  26. color[i][j]=0xff0000; //红色
  27. }
  28. }
  29. w_ret=write(fd, color, 480*800*4);
  30. if(w_ret==-1)//做错误判断
  31. {
  32. perror("write fail");
  33. }
  34. //3.关闭文件
  35. close(fd);
  36. }

arm-linux-gnueabi-gcc -o LCD LCD.c 

 因为用的是自己的编译环境就直接搞了,编译出来的程序文件已经框出来了。

TFTP传输进去开发板,然后添加运行权限运行。

tftp 192.168.5.10 -g -r LCD1
chmod 777 LCD1
./LCD1

 代码效果如下,实在有点简单,代码就不改了。

 2. LCD换个图案

代码贴出来,操作也是和上面那个实验类似。

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. //ssize_t write(int fd, const void *buf, size_t count);
  7. //int open(const char *pathname, int flags);
  8. int main()
  9. {
  10. //1.打开屏幕
  11. int fd=0; //接受open的返回值
  12. fd=open("/dev/fb0", O_RDWR);
  13. if(fd==-1) //做错误判断
  14. {
  15. perror("open hello.c fail");
  16. }
  17. //2.写入颜色数据
  18. int w_ret=0;
  19. int i=0;
  20. int j=0;
  21. unsigned int color[480][800]={0};
  22. for(i=0;i<480;i++)
  23. {
  24. for(j=0;j<800;j++)
  25. {
  26. if((j-400)*(j-400)+(i-240)*(i-240)<=200*200) //(x-x0)*(x-x0) + (y-y0)*(y-y0) =r*r
  27. {
  28. color[i][j]=0xff0000; //红色
  29. }
  30. else
  31. {
  32. color[i][j]=0x000000; //黑色
  33. }
  34. }
  35. }
  36. w_ret=write(fd, color, 480*800*4);
  37. if(w_ret==-1)//做错误判断
  38. {
  39. perror("write fail");
  40. }
  41. //3.关闭文件
  42. close(fd);
  43. }

arm-linux-gnueabi-gcc -o LCD2 LCD.c

 tftp 192.168.5.10 -g -r LCD2
chmod 777 LCD2
./LCD2

 

效果如上,因为前面的三个LCD实验比较简单,过得快一点了,后面的网络编程才是重头戏 

 3. LCD换张图片

代码贴在这里,图片用的是我在实验一用TFTP传输过去的那张,像素为800*480,必须为BMP格式,且必须命名(func.bmp)图片不是我做的,虽然我会,但我不想自己整一张了,就沿用别人发的图片吧

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. #include <unistd.h>
  7. #include <sys/types.h>
  8. #include <unistd.h>
  9. //off_t lseek(int fd, off_t offset, int whence);
  10. //ssize_t read(int fd, void *buf, size_t count);
  11. //ssize_t write(int fd, const void *buf, size_t count);
  12. //int open(const char *pathname, int flags);
  13. int main()
  14. {
  15. //1.打开屏幕
  16. int fd=0; //接受open的返回值
  17. fd=open("/dev/fb0", O_RDWR);
  18. if(fd==-1) //做错误判断
  19. {
  20. perror("open fb0 fail");
  21. }
  22. //打开图片
  23. int bmp_fd=0; //接受open的返回值
  24. bmp_fd=open("./func.bmp", O_RDWR);
  25. if(bmp_fd==-1) //做错误判断
  26. {
  27. perror("open func.bmp fail");
  28. }
  29. //2.偏移54字节
  30. lseek(bmp_fd,54,SEEK_SET);
  31. //3.读取像素数据 800*480
  32. unsigned char bmp[800*480*3]={0};
  33. read(bmp_fd,bmp,sizeof(bmp));
  34. //4.数据处理
  35. /*
  36. bmp[0]--B
  37. bmp[1]--G
  38. bmp[2]--R
  39. bmp[3]--B
  40. ....
  41. lcd[0]=bmp[0] | bmp[1]<<8 | bmp[2]<<16;
  42. lcd[1]=bmp[3] | bmp[4]<<8 | bmp[5]<<16;
  43. lcd[2]=bmp[6] | bmp[7]<<8 | bmp[8]<<16;
  44. */
  45. unsigned int lcd[800*480]={0};
  46. int i=0;
  47. int j=0;
  48. for(i=0;i<800*480;i++)
  49. {
  50. lcd[i]=bmp[3*i] | bmp[3*i+1]<<8 | bmp[3*i+2]<<16;
  51. }
  52. //5.写入屏幕
  53. int w_ret=0;
  54. w_ret=write(fd, lcd, sizeof(lcd));
  55. if(w_ret==-1)//做错误判断
  56. {
  57. perror("write fail");
  58. }
  59. //6.关闭文件
  60. close(bmp_fd);
  61. close(fd);
  62. }

arm-linux-gnueabi-gcc -o LCD3 LCD.c

tftp 192.168.5.10 -g -r LCD3
chmod 777 LCD3
./LCD3

 

效果如上,可以看到图片是颠倒的。下面贴个如何把图片正过来的代码。

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. #include <unistd.h>
  7. #include <sys/types.h>
  8. #include <unistd.h>
  9. //off_t lseek(int fd, off_t offset, int whence);
  10. //ssize_t read(int fd, void *buf, size_t count);
  11. //ssize_t write(int fd, const void *buf, size_t count);
  12. //int open(const char *pathname, int flags);
  13. int main()
  14. {
  15. //1.打开屏幕
  16. int fd=0; //接受open的返回值
  17. fd=open("/dev/fb0", O_RDWR);
  18. if(fd==-1) //做错误判断
  19. {
  20. perror("open fb0 fail");
  21. }
  22. //打开图片
  23. int bmp_fd=0; //接受open的返回值
  24. bmp_fd=open("./func.bmp", O_RDWR);
  25. if(bmp_fd==-1) //做错误判断
  26. {
  27. perror("open func.bmp fail");
  28. }
  29. //2.偏移54字节
  30. lseek(bmp_fd,54,SEEK_SET);
  31. //3.读取像素数据 800*480
  32. unsigned char bmp[800*480*3]={0};
  33. read(bmp_fd,bmp,sizeof(bmp));
  34. //4.数据处理
  35. /*
  36. bmp[0]--B
  37. bmp[1]--G
  38. bmp[2]--R
  39. bmp[3]--B
  40. ....
  41. lcd[0]=bmp[0] | bmp[1]<<8 | bmp[2]<<16;
  42. lcd[1]=bmp[3] | bmp[4]<<8 | bmp[5]<<16;
  43. lcd[2]=bmp[6] | bmp[7]<<8 | bmp[8]<<16;
  44. */
  45. unsigned int temp[800*480]={0};
  46. unsigned int lcd[800*480]={0};
  47. int i=0;
  48. int j=0;
  49. for(i=0;i<800*480;i++)
  50. {
  51. temp[i]=bmp[3*i] | bmp[3*i+1]<<8 | bmp[3*i+2]<<16;
  52. }
  53. for(i=0;i<480;i++)
  54. {
  55. for(j=0;j<800;j++)
  56. {
  57. lcd[(480-1-i)*800+j]=temp[i*800+j];
  58. }
  59. }
  60. //5.写入屏幕
  61. int w_ret=0;
  62. w_ret=write(fd, lcd, sizeof(lcd));
  63. if(w_ret==-1)//做错误判断
  64. {
  65. perror("write fail");
  66. }
  67. //6.关闭文件
  68. close(bmp_fd);
  69. close(fd);
  70. }

 这里省去交叉编译的过程图

 效果图如上,其实就是把图反着写入。

在这里把执行的程序文件放上来,大伙自己烧板子自己试哈

链接:https://pan.baidu.com/s/1BuQ5Q2FEGbgdJ1yEr4o86w 
提取码:1234 

4.网线登录

啧...我觉得这个可能没太大必要,虽然好像可以省一个串口,但还不如串口换成个带5V的TYPEC,也是两条线,搞这个不如整个WiFi模块远程无线调试,我不做了,但里面有一个过程比较有价值,就是更改开机脚本的

vi /etc/profile

其实就是改ifconfig之后得到的开发板的网卡IP,我这里是改成了192.168.5.9,需要的话改,不需要就每次开机都输入一条

ifconfig eth0 192.168.5.9

5.触屏电子相册

我靠,晴天霹雳,完成这东西需要整多几张图,太难受了

 然后在图画另存为bmp格式就行,我做的是这三张。

 下面贴出代码:

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. #include <unistd.h>
  7. #include <sys/types.h>
  8. #include <unistd.h>
  9. #include <sys/mman.h>
  10. #include <linux/input.h>
  11. //void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
  12. //off_t lseek(int fd, off_t offset, int whence);
  13. //ssize_t read(int fd, void *buf, size_t count);
  14. //ssize_t write(int fd, const void *buf, size_t count);
  15. //int open(const char *pathname, int flags);
  16. //函数声明
  17. int show_bmp(const char *bmpname);
  18. int show_anybmp(const char *bmpname);
  19. int show_anywherebmp(int x0,int y0,const char *bmpname);
  20. int get_xy(int *x,int *y);
  21. int main()
  22. {
  23. int x=-1;
  24. int y=-1;
  25. int tmp=0;
  26. char photo[][30]={"./1.bmp","./2.bmp","./3.bmp"};
  27. //1.显示主界面
  28. show_anybmp("./func.bmp"); //规则界面
  29. while(1)
  30. {
  31. //2.获取坐标
  32. get_xy(&x,&y);
  33. if(x>=400) //下一张
  34. {
  35. tmp=(tmp+1)%3;
  36. show_bmp(photo[tmp]);
  37. }
  38. else if(x<400) //上一张
  39. {
  40. tmp=tmp-1;
  41. if(tmp==-1){
  42. tmp=2;
  43. }
  44. show_bmp(photo[tmp]);
  45. }
  46. //用完坐标得清零 坐标
  47. x=-1;
  48. y=-1;
  49. }
  50. }
  51. //函数实现
  52. //显示800*480的图片
  53. int show_bmp(const char *bmpname)
  54. {
  55. //1.打开屏幕
  56. int fd=0; //接受open的返回值
  57. fd=open("/dev/fb0", O_RDWR);
  58. if(fd==-1) //做错误判断
  59. {
  60. perror("open fb0 fail");
  61. }
  62. //建立屏幕映射
  63. unsigned int* lcd = mmap(NULL, 800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
  64. //打开图片
  65. int bmp_fd=0; //接受open的返回值
  66. bmp_fd=open(bmpname, O_RDWR);
  67. if(bmp_fd==-1) //做错误判断
  68. {
  69. perror("open func.bmp fail");
  70. }
  71. //2.偏移54字节
  72. lseek(bmp_fd,54,SEEK_SET);
  73. //3.读取像素数据 800*480
  74. unsigned char bmp[800*480*3]={0};
  75. read(bmp_fd,bmp,sizeof(bmp));
  76. //4.数据处理
  77. /*
  78. bmp[0]--B
  79. bmp[1]--G
  80. bmp[2]--R
  81. bmp[3]--B
  82. ....
  83. lcd[0]=bmp[0] | bmp[1]<<8 | bmp[2]<<16;
  84. lcd[1]=bmp[3] | bmp[4]<<8 | bmp[5]<<16;
  85. lcd[2]=bmp[6] | bmp[7]<<8 | bmp[8]<<16;
  86. */
  87. unsigned int temp[800*480]={0};
  88. int i=0;
  89. int j=0;
  90. for(i=0;i<800*480;i++)
  91. {
  92. temp[i]=bmp[3*i] | bmp[3*i+1]<<8 | bmp[3*i+2]<<16;
  93. }
  94. //解决上下颠倒 把一维数组 二维化思考
  95. for(i=0;i<480;i++)
  96. {
  97. for(j=0;j<800;j++)
  98. {
  99. lcd[(480-1-i)*800+j]=temp[i*800+j];
  100. }
  101. }
  102. //解除映射
  103. munmap(lcd,800*480*4);
  104. //6.关闭文件
  105. close(bmp_fd);
  106. close(fd);
  107. }
  108. //显示任意大小图片
  109. int show_anybmp(const char *bmpname)
  110. {
  111. //1.打开屏幕
  112. int fd=0; //接受open的返回值
  113. fd=open("/dev/fb0", O_RDWR);
  114. if(fd==-1) //做错误判断
  115. {
  116. perror("open fb0 fail");
  117. }
  118. //建立屏幕映射
  119. unsigned int* lcd = mmap(NULL, 800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
  120. //打开图片
  121. int bmp_fd=0; //接受open的返回值
  122. bmp_fd=open(bmpname, O_RDWR);
  123. if(bmp_fd==-1) //做错误判断
  124. {
  125. perror("open func.bmp fail");
  126. }
  127. //2.偏移54字节
  128. //先提取到宽
  129. lseek(bmp_fd,18,SEEK_SET);
  130. int w=0;
  131. read(bmp_fd,&w,4);
  132. //printf("w=%d\n",w);//打印宽度信息
  133. //再提取高
  134. lseek(bmp_fd,22,SEEK_SET);
  135. int h=0;
  136. read(bmp_fd,&h,4);
  137. //printf("h=%d\n",h);//打印宽度信息
  138. lseek(bmp_fd,54,SEEK_SET);
  139. //3.读取像素数据 800*480
  140. unsigned char bmp[w*h*3];
  141. read(bmp_fd,bmp,sizeof(bmp));
  142. //4.数据处理
  143. /*
  144. bmp[0]--B
  145. bmp[1]--G
  146. bmp[2]--R
  147. bmp[3]--B
  148. ....
  149. lcd[0]=bmp[0] | bmp[1]<<8 | bmp[2]<<16;
  150. lcd[1]=bmp[3] | bmp[4]<<8 | bmp[5]<<16;
  151. lcd[2]=bmp[6] | bmp[7]<<8 | bmp[8]<<16;
  152. */
  153. unsigned int temp[800*480]={0};
  154. int i=0;
  155. int j=0;
  156. for(i=0;i<w*h;i++)
  157. {
  158. temp[i]=bmp[3*i] | bmp[3*i+1]<<8 | bmp[3*i+2]<<16;
  159. }
  160. //解决上下颠倒 把一维数组 二维化思考
  161. for(i=0;i<h;i++)
  162. {
  163. for(j=0;j<w;j++)
  164. {
  165. lcd[(h-1-i)*800+j]=temp[i*w+j];
  166. }
  167. }
  168. //解除映射
  169. munmap(lcd,800*480*4);
  170. //6.关闭文件
  171. close(bmp_fd);
  172. close(fd);
  173. }
  174. //在指定位置显示图片 x0,y0为起点坐标
  175. int show_anywherebmp(int x0,int y0,const char *bmpname)
  176. {
  177. //1.打开屏幕
  178. int fd=0; //接受open的返回值
  179. fd=open("/dev/fb0", O_RDWR);
  180. if(fd==-1) //做错误判断
  181. {
  182. perror("open fb0 fail");
  183. }
  184. //建立屏幕映射
  185. unsigned int* lcd = mmap(NULL, 800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
  186. //打开图片
  187. int bmp_fd=0; //接受open的返回值
  188. bmp_fd=open(bmpname, O_RDWR);
  189. if(bmp_fd==-1) //做错误判断
  190. {
  191. perror("open func.bmp fail");
  192. }
  193. //2.偏移54字节
  194. //先提取到宽
  195. lseek(bmp_fd,18,SEEK_SET);
  196. int w=0;
  197. read(bmp_fd,&w,4);
  198. printf("w=%d\n",w);//打印宽度信息
  199. //再提取高
  200. lseek(bmp_fd,22,SEEK_SET);
  201. int h=0;
  202. read(bmp_fd,&h,4);
  203. printf("h=%d\n",h);//打印宽度信息
  204. lseek(bmp_fd,54,SEEK_SET);
  205. //3.读取像素数据 800*480
  206. unsigned char bmp[w*h*3];
  207. read(bmp_fd,bmp,sizeof(bmp));
  208. //4.数据处理
  209. /*
  210. bmp[0]--B
  211. bmp[1]--G
  212. bmp[2]--R
  213. bmp[3]--B
  214. ....
  215. lcd[0]=bmp[0] | bmp[1]<<8 | bmp[2]<<16;
  216. lcd[1]=bmp[3] | bmp[4]<<8 | bmp[5]<<16;
  217. lcd[2]=bmp[6] | bmp[7]<<8 | bmp[8]<<16;
  218. */
  219. unsigned int temp[800*480]={0};
  220. int i=0;
  221. int j=0;
  222. for(i=0;i<w*h;i++)
  223. {
  224. temp[i]=bmp[3*i] | bmp[3*i+1]<<8 | bmp[3*i+2]<<16;
  225. }
  226. //解决上下颠倒 把一维数组 二维化思考
  227. for(i=0;i<h;i++)
  228. {
  229. for(j=0;j<w;j++)
  230. {
  231. lcd[(h-1-i+y0)*800+j+x0]=temp[i*w+j];
  232. }
  233. }
  234. //解除映射
  235. munmap(lcd,800*480*4);
  236. //6.关闭文件
  237. close(bmp_fd);
  238. close(fd);
  239. }
  240. int get_xy(int *x,int *y)
  241. {
  242. int count=0;
  243. //1.打开触摸屏
  244. int tsfd =open("/dev/input/event0",O_RDWR);
  245. if(tsfd == -1)
  246. {
  247. perror("open ts fail");
  248. }
  249. //2.read
  250. struct input_event ts;
  251. while(1)
  252. {
  253. read(tsfd,&ts,sizeof(struct input_event));
  254. //筛选
  255. if(ts.type ==EV_ABS && ts.code==ABS_X )
  256. {
  257. *x=ts.value; //适合蓝底屏幕
  258. //*x= ts.value*800/1024; //适合黑底屏幕
  259. count++;
  260. }
  261. if(ts.type ==EV_ABS && ts.code==ABS_Y )
  262. {
  263. *y=ts.value; //适合蓝底屏幕
  264. //*y= ts.value*480/600; //适合黑底屏幕
  265. count++;
  266. }
  267. if(count == 2)
  268. {
  269. break;
  270. }
  271. }
  272. //关闭触摸屏
  273. close(tsfd);
  274. }

arm-linux-gnueabi-gcc -o touch LCD_drv_touch.c

 

 

 效果如下:

效果

6.网络编程(TCP通信)

因为我没听课,所以就不知道他做的什么内容了..这部分我确实没学过,本来打算是寒假去学的,刚刚好,他竟然教了。

前面还有一个多线程的实验,因为不难我就不做了,拿gcc编译工具在UBUNTU上跑就行

代码贴出来

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. #include <unistd.h>
  7. #include <sys/types.h>
  8. #include <unistd.h>
  9. #include <sys/mman.h>
  10. #include <linux/input.h>
  11. #include <pthread.h>
  12. //int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
  13. //线程任务函数
  14. void *pth_function1(void *arg)
  15. {
  16. while(1)
  17. {
  18. printf("你真帅!!!\n");
  19. sleep(1);//延时一秒
  20. }
  21. }
  22. //主线程
  23. int main()
  24. {
  25. pthread_t thid; //定义线程ID
  26. //创建一个新的线程,默认属性 任务函数 不传参
  27. pthread_create(&thid, NULL, pth_function1, NULL);
  28. while(1)
  29. {
  30. printf("年轻人不讲武德!!!\n");
  31. sleep(1);//延时一秒
  32. }
  33. }
gcc pth.c -o pth -pthread

 然后是第一个实验,TCP的客户端与服务端间的通信

ifconfig

 需要改这里:

 服务端代码:(server.c)

  1. #include <stdio.h>
  2. #include <sys/types.h> /* See NOTES */
  3. #include <sys/socket.h>
  4. #include<netinet/in.h>
  5. #include<arpa/inet.h>
  6. #include <strings.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9. #include <pthread.h>
  10. #include <stdlib.h>
  11. #include <sys/stat.h>
  12. #include <fcntl.h>
  13. #include <sys/ioctl.h>
  14. #include <linux/fb.h>
  15. #include <sys/mman.h>
  16. #include <linux/input.h>
  17. //int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  18. //int listen(int sockfd, int backlog);
  19. //int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  20. //int socket(int domain, int type, int protocol);
  21. int main()
  22. {
  23. //1.创建socket
  24. int skfd=socket(AF_INET ,SOCK_STREAM, 0);
  25. if(skfd == -1)
  26. {
  27. perror("socket fail");
  28. }
  29. else
  30. {
  31. printf("socket ok\n");
  32. }
  33. //2.bind IP和端口号
  34. //定义结构体
  35. struct sockaddr_in seraddr={0};
  36. seraddr.sin_family=AF_INET; //IPV4
  37. seraddr.sin_port= htons(12345);
  38. //端口号 http-80 8080 Telnet--23 范围:0~65535 个人编程的时候建议5位数的端口号
  39. //htons() 把本地转换为网络序 认识大端和小端存储
  40. seraddr.sin_addr.s_addr=htonl(INADDR_ANY);
  41. //htonl() 课后 认识一下 转换为网络序 INADDR_ANY--0.0.0.0--表示自动获取本机IP
  42. int b_ret=bind(skfd, (struct sockaddr*)&seraddr,sizeof(seraddr));
  43. if(b_ret !=0)
  44. {
  45. perror("bind fail");
  46. }
  47. else
  48. {
  49. printf("bind ok\n");
  50. }
  51. //3.listen--等待连接
  52. int l_ret = listen(skfd,3);
  53. if(l_ret!=0)
  54. {
  55. perror("listen fail");
  56. }
  57. else
  58. {
  59. printf("listen ok\n");
  60. }
  61. //4.accept
  62. struct sockaddr_in cliaddr={0}; //为了存储连接的客户端信息
  63. int len=sizeof(cliaddr);
  64. int newskfd=accept(skfd,(struct sockaddr*)&cliaddr, &len);
  65. if(newskfd == -1)
  66. {
  67. perror("accept fail");
  68. return -1;
  69. }
  70. else
  71. {
  72. printf("accept ok\n");
  73. printf("newskfd=%d,client-ip:%s,client-port:%d\n",newskfd,inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));
  74. }
  75. //5.read/write 服务器一直接收
  76. char buf[1024]={0};
  77. while(1)
  78. {
  79. read(newskfd,buf,sizeof(buf)); //读取消息
  80. printf("buf=%s\n",buf); //打印消息
  81. if( strcmp(buf,"exit") == 0) //字符串的判断
  82. {
  83. break; //跳出循环 关闭通信
  84. }
  85. memset(buf,0,sizeof(buf)); //清空数组
  86. }
  87. //6. 关闭通信
  88. close(skfd);
  89. }

 客户端代码:(client.c)

  1. #include <stdio.h>
  2. #include <sys/types.h> /* See NOTES */
  3. #include <sys/socket.h>
  4. #include<netinet/in.h>
  5. #include<arpa/inet.h>
  6. #include <strings.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9. #include <pthread.h>
  10. #include <stdlib.h>
  11. #include <sys/stat.h>
  12. #include <fcntl.h>
  13. #include <sys/ioctl.h>
  14. #include <linux/fb.h>
  15. #include <sys/mman.h>
  16. #include <linux/input.h>
  17. //int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  18. //int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  19. //int listen(int sockfd, int backlog);
  20. //int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  21. //int socket(int domain, int type, int protocol);
  22. int main()
  23. {
  24. //1.创建socket
  25. int skfd=socket(AF_INET ,SOCK_STREAM, 0);
  26. if(skfd == -1)
  27. {
  28. perror("socket fail");
  29. }
  30. else
  31. {
  32. printf("socket ok\n");
  33. }
  34. //2.发起连接请求 connect
  35. struct sockaddr_in seraddr={0};
  36. seraddr.sin_family=AF_INET; //IPV4
  37. seraddr.sin_port= htons(12345);
  38. //端口号 http-80 8080 Telnet--23 范围:0~65535 个人编程的时候建议5位数的端口号
  39. //htons() 把本地转换为网络序 认识大端和小端存储
  40. seraddr.sin_addr.s_addr=inet_addr( "192.168.42.168"); //服务器的地址
  41. //htonl() 课后 认识一下 转换为网络序 INADDR_ANY--0.0.0.0--表示自动获取本机IP
  42. int c_ret=connect(skfd, (struct sockaddr*)&seraddr,sizeof(seraddr));
  43. if(c_ret!=0)
  44. {
  45. perror("connect fail");
  46. return -1;
  47. }
  48. else
  49. {
  50. printf("connect ok\n");
  51. }
  52. //3.read /write 通信:客户端一直发消息
  53. char buf[1024]={0};
  54. while(1)
  55. {
  56. printf("请输入要发送的消息:\n");
  57. scanf("%s",buf);
  58. write(skfd,buf,strlen(buf)); //发送消息
  59. if(strcmp(buf,"exit")==0) //判断消息为退出关键字
  60. {
  61. break;
  62. }
  63. printf("buf=%s\n",buf);
  64. }
  65. //4.关闭通信
  66. close(skfd);
  67. }

 效果如下:

 7.网络编程(UDP通信)

直接贴代码了,比较简单,难在理解整个过程,不然代码是没法写的

 本机UBUNTUip为192.168.5.11,想要啥设备接收就写哪个设备的ip

服务端(server.c)

  1. #include <stdio.h>
  2. #include <sys/types.h> /* See NOTES */
  3. #include <sys/socket.h>
  4. #include<netinet/in.h>
  5. #include<arpa/inet.h>
  6. #include <strings.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9. #include <pthread.h>
  10. #include <stdlib.h>
  11. #include <sys/stat.h>
  12. #include <fcntl.h>
  13. #include <sys/ioctl.h>
  14. #include <linux/fb.h>
  15. #include <sys/mman.h>
  16. #include <linux/input.h>
  17. //ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
  18. int main()
  19. {
  20. //1.创建socket
  21. int skfd=socket(AF_INET ,SOCK_DGRAM, 0);
  22. if(skfd == -1)
  23. {
  24. perror("socket fail");
  25. }
  26. else
  27. {
  28. printf("socket ok\n");
  29. printf("skfd=%d\n",skfd);
  30. }
  31. int s_ret=0; //返回值
  32. char buf[512]={0}; //存储读取内容
  33. struct sockaddr_in seraddr={0}; //来自客户端地址
  34. seraddr.sin_family=AF_INET; //IPV4
  35. seraddr.sin_port= htons(12345);
  36. //端口号 http-80 8080 Telnet--23 范围:0~65535 个人编程的时候建议5位数的端口号
  37. //htons() 把本地转换为网络序 认识大端和小端存储
  38. seraddr.sin_addr.s_addr=inet_addr( "192.168.5.11"); //服务器的地址
  39. //htonl() 课后 认识一下 转换为网络序 INADDR_ANY--0.0.0.0--表示自动获取本机IP
  40. socklen_t addrlen=sizeof(seraddr); //地址长度
  41. while(1)
  42. {
  43. printf("请输入发送的消息\n");
  44. scanf("%s",buf);
  45. s_ret=sendto(skfd,buf, strlen(buf),0,(struct sockaddr*)&seraddr, addrlen);
  46. //面试题 strlen 和 sizeof 对比
  47. if(s_ret==-1)
  48. {
  49. perror("sendto fail");
  50. }
  51. if(strcmp(buf,"exit")== 0)
  52. {
  53. break;
  54. }
  55. memset(buf,0,sizeof(buf)); //用完之后清空
  56. }
  57. //关闭通信
  58. close(skfd);
  59. }

 客户端(client.c)

  1. #include <stdio.h>
  2. #include <sys/types.h> /* See NOTES */
  3. #include <sys/socket.h>
  4. #include<netinet/in.h>
  5. #include<arpa/inet.h>
  6. #include <strings.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9. #include <pthread.h>
  10. #include <stdlib.h>
  11. #include <sys/stat.h>
  12. #include <fcntl.h>
  13. #include <sys/ioctl.h>
  14. #include <linux/fb.h>
  15. #include <sys/mman.h>
  16. #include <linux/input.h>
  17. //ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
  18. int main()
  19. {
  20. //1.创建socket
  21. int skfd=socket(AF_INET ,SOCK_DGRAM, 0);
  22. if(skfd == -1)
  23. {
  24. perror("socket fail");
  25. }
  26. else
  27. {
  28. printf("socket ok\n");
  29. printf("skfd=%d\n",skfd);
  30. }
  31. //2.bind IP和端口号
  32. //定义结构体
  33. struct sockaddr_in seraddr={0};
  34. seraddr.sin_family=AF_INET; //IPV4
  35. seraddr.sin_port= htons(12345);
  36. //端口号 http-80 8080 Telnet--23 范围:0~65535 个人编程的时候建议5位数的端口号
  37. //htons() 把本地转换为网络序 认识大端和小端存储
  38. seraddr.sin_addr.s_addr=htonl(INADDR_ANY);
  39. //htonl() 课后 认识一下 转换为网络序 INADDR_ANY--0.0.0.0--表示自动获取本机IP
  40. int b_ret=bind(skfd, (struct sockaddr*)&seraddr,sizeof(seraddr));
  41. if(b_ret !=0)
  42. {
  43. perror("bind fail");
  44. }
  45. else
  46. {
  47. printf("bind ok\n");
  48. }
  49. int r_ret=0; //返回值
  50. char buf[512]={0}; //存储读取内容
  51. struct sockaddr_in cliaddr={0}; //来自客户端地址
  52. socklen_t addrlen=sizeof(cliaddr); //地址长度
  53. while(1)
  54. {
  55. //接收消息
  56. r_ret=recvfrom(skfd, buf,sizeof(buf),0,(struct sockaddr*)&cliaddr, &addrlen);
  57. if(r_ret == -1)
  58. {
  59. perror("recvfrom fail");
  60. }
  61. else
  62. {
  63. printf("from %s:%s\n",inet_ntoa(cliaddr.sin_addr),buf);
  64. }
  65. if(strcmp(buf,"exit")==0)//判断消息内容
  66. {
  67. break;
  68. }
  69. memset(buf,0,sizeof(buf)); //用完之后清空
  70. memset(&cliaddr,0,sizeof(cliaddr));
  71. }
  72. //关闭通信
  73. close(skfd);
  74. }

8.开发板串口通信MCU(32或Zigbee节点)

 这个功能确实是我想学的..

但很难受,手头上没杜邦线

这里做一个开发板多线程自己通信自己

贴出来代码:

  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <termios.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. int set_serial_uart(int ser_fd)
  9. {
  10. struct termios new_cfg,old_cfg;
  11. /*保存并测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息*/
  12. if (tcgetattr(ser_fd, &old_cfg) != 0)
  13. {
  14. perror("tcgetattr");
  15. return -1;
  16. }
  17. bzero( &new_cfg, sizeof(new_cfg));
  18. /*原始模式*/
  19. /* 设置字符大小*/
  20. new_cfg = old_cfg;
  21. cfmakeraw(&new_cfg); /* 配置为原始模式 */
  22. /*波特率为115200*/
  23. cfsetispeed(&new_cfg, B115200);
  24. cfsetospeed(&new_cfg, B115200);
  25. //用于本地连接和接受使能
  26. new_cfg.c_cflag |= CLOCAL | CREAD;
  27. /*8位数据位*/
  28. new_cfg.c_cflag &= ~CSIZE;
  29. new_cfg.c_cflag |= CS8;
  30. /*无奇偶校验位*/
  31. new_cfg.c_cflag &= ~PARENB;
  32. /*1位停止位*/
  33. new_cfg.c_cflag &= ~CSTOPB;
  34. /*清除串口缓冲区*/
  35. tcflush( ser_fd,TCIOFLUSH);
  36. new_cfg.c_cc[VTIME] = 0; //等待时间
  37. new_cfg.c_cc[VMIN] = 1; //最少接收字节数
  38. tcflush ( ser_fd, TCIOFLUSH);
  39. /*串口设置使能*/
  40. tcsetattr( ser_fd ,TCSANOW,&new_cfg);
  41. }
  42. int main(void)
  43. {
  44. int ret;
  45. char buf[10];
  46. //打开串口 0
  47. int fd = open("/dev/ttyUSB0" , O_RDWR|O_NOCTTY);
  48. if(fd < 0)
  49. {
  50. perror ("open failed");
  51. return 0;
  52. }
  53. set_serial_uart(fd);
  54. while(1)
  55. {
  56. bzero(buf, 10);
  57. ret = read(fd , buf , 10-1); // 留一个位置给‘\0'
  58. if(ret <= 0 )
  59. {
  60. perror("write failed");
  61. break;
  62. }
  63. printf("I GOT : %s \n", buf); // 打印
  64. }
  65. }

硬件连接如下:

用的善学坊的一款板子,板载ch340,接收路由器设备采集到的光照强度数据,温湿度数据发送到协调器,然后协调器再通过USB0发送给开发板。

 开发板接收到数据如下,有点冷...

9.EDP接入onenet

哇,真的是不想搞这玩意,没想到又遇到了,之前弄完之后把环境全删掉了,觉得有点没意思,现在用的stm32连接onenet,至于MQTT通信,因为在学这玩意之前先去学了ros通信,其实也就差不多,就是客户端发布话题,服务端订阅,差别就差在ros通信里面有个通信的master。

 开发实例_开发者文档_OneNET

但MQTT的环境有点问题,所以在这里先把EDP的通信解决了。

我不知道你们界面是不是这样:

 这里有个多协议接入,我们要用到的EDP协议貌似只有这里有

或者以这种形式也能进去

 选择EDP,点击添加产品

 主要是设备接入协议那里选择EDP就行,其他随便

 添加完就是这样了,点击下面的位置进入

 点击设备列表再点击添加设备

 填写只需注意鉴权信息就行

 添加好后如下,点击详情

 添加APIkey后将这三个信息记录下来

 放入记事本

 点击数据流模板,再点击添加数据流模板

 因为代码内设置的是Temp,所以这里也就用Temp了,但实际上这东西按理讲是不用加的,当数据上传上来就会自动生成才是。

 设置好后如下

 然后就是改代码了,代码用的是老师给的一份代码,在这里直接贴链接了

链接:https://pan.baidu.com/s/1FxXrvckHxBiyX9E-HZakgA 
提取码:1234 

更改代码如下,分别是设备ID及API密钥

 可以看到,该代码将会上传一个名为Temp的数据流,并且该数据将不断加1,到100,再清0

 直接放到UBUNTU上编译就行,可以看到,选中的为执行文件

 运行

设备连接成功

 数据流如下

 然后就是试一下,将该代码用在开发板上了,怎么用呢,首先得让开发板连上网吧?..

这就涉及到我的知识盲区了..

先不管了,先把开机脚本改一下:

vi /etc/profile

 先把这两行注释掉,屏蔽开发板的嵌入式物联网综合实验箱

 然后再配置上网

怎么找信息呢..我是连上了从路由器接过来的网线到电脑上

点击这里 

 自动配置IP

 可以看到IPV4地址在该机为192.168.1.5

 这信息不就来了嘛

 所以开发板内就这样配置

哎,每次进入这个开机程序之后,只要这个串口线一松,就掉出界面,然后就拒绝访问,我是真的烦,所以我就直接输了

    ifconfig eth0 up
    ifconfig eth0 192.168.1.6
    route add default gw 192.168.1.1
    echo "nameserver 114.114.114.114" > /etc/resolv.conf
    echo "search lan" >> /etc/resolv.conf

 然后来到更改适配器选项这里

 用哪个网卡改哪个网卡,右键属性

 

 

 配置就结束了。

 然后把网线插到开发板上,哇这网络延迟,ping是ping通了,感觉这延迟不对劲啊

 现在说明开发板能连上网了

然后就是改代码了,这份代码也是现成的,需要改的部分和之前一致。

这里直接贴链接了

链接:https://pan.baidu.com/s/1yxfU5qXSzRodnv8JJjQSAg 
提取码:1234 

这里只需要把交叉编译工具链改成自己的就行

 编译出的程序文件如下

 把它扔到开发板运行试试

因为网口被占用被迫用回RX工具了..

 运行发现,开发板已经连上onenet了

 显示在线

 数据正常

 下发个数据试试

 正常

10.MQTT协议接入onenet

这个..需要配置

openssl-OpenSSL_1_0_2q,paho.mqtt.c-1.3.0
  1. (编译paho时需打开PAHO_WITH_SSL选项)
  2. 直接跟着走就行

 首先还是这个界面,但用的是MQTT物联网套件

 点击添加产品

 重点还是这个接入协议

 点进去

 设备列表,添加设备

 信息随便设置

 然后就是要改代码了

直接贴上来了

链接:https://pan.baidu.com/s/1daXTwM9xmNwG62TnBOYvDw 
提取码:1234 

 要改如下几个部分,分别对应于以下几个位置的信息

 

 

 const char *server_url = "ssl://mqttstls.heclouds.com:8883";

 然后Cmakelist.txt中需要加一个参数

 代码就算改完了,然后是环境配置

 把代码扔上ubuntu后

安装CMake

 sudo apt install cmake

 安装OpenSSL

sudo apt-get install libssl-dev

 安装paho.mqtt.c

  1. git clone https://github.com/eclipse/paho.mqtt.c.git
  2. cd paho.mqtt.c
  3. //修改编辑CMakeLists.txt文件,打开PAHO_WITH_SSL,编辑下图所示的位置,将FALSR改为TRUE

//修改编辑CMakeLists.txt文件,将FALSR改为TRUE

  1. make clean
  2. make
  3. sudo make install

 编译示例代码:

  1. cmake .
  2. make clean
  3. make

 链接onenet成功

 如下

 11.ZIGBEE发送数据,由6818开发板接收后发送到ONENET

 硬件连接如下,可以看到,协调器通过USB0连接到6818开发板,然后路由器节点连接到电脑(仅供电,)6818开发板连接网线与电脑通过RS232串口线相连(需要上网和串口调试)

 这里直接贴用的代码了

链接:https://pan.baidu.com/s/18w0fwo3Zz8gmhAKkiTzEgA 
提取码:1234 
ZIGBEE代码就不给了,我这里的ZIGBEE是把温度湿度光照强度,三个数放在一个字符串变量里面,到时候直接开发板自己拆分解决

 对比一下数据流

 下发命令呢?也正常

12.开发板接收onenet下发命令通过协调器控制路由器开关灯

 

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号