找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3367|回复: 5
打印 上一主题 下一主题
收起左侧

基于STM32的可见光通信系统程序设计

  [复制链接]
跳转到指定楼层
楼主
目前已完成,2m距离,传输10000个连续数字,每个数字两字节大小,即总共20000个字节160000bit,用时7s,大约2.3万bit/s,即22.4kB/s,误码率为0






发射与接收程序:

  1. #include "stm32f10x.h"
  2. #include "delay.h"
  3. #include "sensor.h"
  4. #include "usart.h"
  5. #include "usmart.h"

  6. /*
  7.    程序整体思路:
  8.            ① 把每个要发射的数据转成二进制,再将二进制的每一位逐1发射出去;
  9.                  ② 需要3个信号表示一个数据,分别用高电平持续的不同时间表示不同
  10.                    信号:起始信号、0信号、1信号,分别对应p1,p2,p3;
  11.                  ③ 默认状态LED是亮的,起始信号发射的时候,将LED引脚置高,并延迟
  12.                          p1的时间,再进行翻转,两次这样的p1高电平时间即代表起始信号;
  13.                  ④ 数据信号需要紧跟着起始信号,一次起始信号之后就是16位的0、1数
  14.                    据信号,对于0信号,则是高电平持续p2时间,再翻转,对于1信号,
  15.                          则是高电平持续p3时间;
  16.                  ⑤ 因此只需要设置好每个信号之间的时间参数,使用滴答定时器计数的
  17.                    延迟函数达到持续的效果,然后只要判断即将发射的数据的各个位,
  18.                          即可将一个数据发射出去。
  19.                         
  20. *        2020.8.30 —— by afeng
  21.     1、优化程序,优化部分变量,让程序运行的更快,尽量与接收端同步。

  22. *        2020.8.25 —— by afeng
  23.     1、优化发射端串口助手,使其能够实时自动刷新电脑可用的串口,当该串口掉线,则会自动关闭连接。
  24.                 2、优化串口助手的显示区域部分,通过设置光标的位置使得文字可以从上至下显示。

  25. *        2020.8.23 —— by afeng
  26.     1、加入连续发射多个数据的函数,并支持不同起始数据和结束数据,然后
  27.                    注册到USMART调试组件,以达到从串口助手来控制发射的数据。
  28.                 2、结合了自己的基于QT的串口助手,把本工程的USMART组件与该调试助手
  29.                    结合起来使用,更方便调参。

  30. *        2020.8.20 —— by afeng
  31.     1、开始使用USMART调试组件,可以在串口助手通过函数带参数的方式在线修改
  32.                    各个参数,在后面不同距离下改变参数有着极大的便利性,免去了重复修改
  33.                          、编译和烧录代码的繁琐过程。
  34.           2、解决了二进制数据位错误的BUG,是由于自己不够熟练位操作引起的,最后
  35.                    决定使用数字1的移位操作来提取出每个数据的各个二进制位。
  36.                 3、实现了基于滴答定时器的长时间延迟,由于该定时器只有16位,基于ST库写
  37.                    的延迟函数一次最大不能超过2s,经过额外编程实现能够一次延迟10s以上。
  38.                 4、剔除了每次数据都需要结束信号的方案,使得发射时间进一步提升,其实每
  39.                    个数据的起始信号也可以作为每个数据的区分了。
  40.                         
  41. *        2020.8.19 —— by afeng
  42.     1、使用函数将十进制转二进制,并能够将每一个位通过亮-暗表示0-1将二进制
  43.                    各个位成功发射出去,测得最小时间参数可以达到300us左右,但是由于接收
  44.                          端的限制以及距离的影响,这个参数需要每次调整。
  45. */


  46. //连续发射数据
  47. void emitSeriesData(uint16_t start,uint16_t end)
  48. {
  49.         uint16_t i,len=end+1;
  50.         if((start>0) && (end>start))
  51.         {
  52.                 printf("发送从 %d 到 %d ,共 %d 个数据。\r\n",start,end,(end+1-start));
  53.                 printf("正在发送……\r\n");
  54.                 emitData(start); emitData(end); emitData((end+1-start)); //先发送本次数据块的信息
  55.                 delay_ms(10);
  56.                 for(i=start;i<len;i++)
  57.                 {
  58.                         emitData(i); //开始循环发送,从开始数据位开始发送
  59.                         if(i%100 == 0) printf("%d ",i);
  60.                 }
  61.                 LED = 0;
  62.                 printf("\r\n本次已发送完成。\r\n");
  63.         }
  64. }

  65. int main(void)
  66. {        
  67.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);          //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
  68.         uart_init(115200);         //串口初始化为115200
  69.         delay_init();                     //延时函数初始化         
  70.         LedConfigInit();  //初始化光源引脚及发射相关参数
  71.         usmart_dev.init(SystemCoreClock/1000000); //初始化 USMART,实现在串口修改发射相关参数
  72.         LED = 0;  //发射前默认光源开启
  73.         printf("当前参数:\r\n"); lookUpCurrentParameter();
  74.         printf("\r\n等待发射数据……\r\n");
  75.         emitSeriesData(1,5);
  76.         while(1)
  77.         {
  78.                  //直到等到发射命令从串口进入,才进行发射
  79.                
  80.         }
  81. }
复制代码


  1. #define  dataLen 12000
  2. uint16_t dataBuf[dataLen] __attribute__((at(Bank1_SRAM3_ADDR)));
  3. uint16_t dataCurrentPos=0;

  4. int main(void)
  5. {        
  6.         uint16_t recvWorkCounts=0;
  7.         uint8_t j=0,startRecvFlag=0;
  8.         uint16_t i=0,recvData,dataInfo[3]; //dataInfo用来检验一次数据接收的起始数据和结尾数据
  9.         uint16_t errorCounts=0; //用来记录接收错误的数据个数
  10.         uint32_t recvTime_us;  //用来记录接收用时
  11.         
  12.   delay_init();                     //延时函数初始化
  13.         uart_init(115200);         //串口初始化为115200
  14.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);          //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
  15.         TIM3_CountTime_Init(); //用于计时接收数据的时间
  16.   LdrConfigInit();  //初始化光敏传感器的引脚和输入捕获功能
  17.         usmart_dev.init(SystemCoreClock/1000000); //初始化 USMART,实现在串口修改接收相关参数
  18.         FSMC_SRAM_Init();                        //初始化外部SRAM
  19.         LCD_Init();

  20.         memset(dataBuf,0,sizeof(dataBuf)); //全都初始化为0
  21.         
  22.         POINT_COLOR=RED;//设置字体为红色
  23.         LCD_ShowString(60,50,200,16,16,"My Class Design");        
  24.         LCD_ShowString(60,70,200,16,16,"2020-9-4 @By afeng");        
  25.         LCD_ShowString(60,90,230,16,16,"Visible Light Communication.");
  26.         POINT_COLOR=BLUE;//设置字体为蓝色
  27.         LCD_ShowString(60,160,200,16,24,"WorkCounts  :");
  28.         LCD_ShowString(60,200,200,16,24,"errorCounts :"); //LCD_ShowNum(230,200,10000,5,24)
  29.         LCD_ShowString(60,240,200,16,24,"usingTime/us:"); //LCD_ShowNum(230,240,200000000,9,24)
  30.         POINT_COLOR=BLACK;
  31.         LCD_ShowNum(230,160,0,9,24);
  32.         LCD_ShowNum(230,200,0,9,24);
  33.         LCD_ShowNum(230,240,0,9,24);
  34.         
  35.         printf("等待接收数据……\r\n");
  36.         while(1)
  37.         {
  38.                 recvData = receiveData();  //阻塞等待接收一个数据
  39.                
  40.                 if((!startRecvFlag) && recvData)  //先接收起始数据和结束数据、及总的长度
  41.                 {
  42.                         dataInfo[j] = recvData;
  43.                         j++;
  44.                         if(j==3)
  45.                         {
  46.                                 j = 0; //若结束+1-起始 = 长度,则准备进入接收数据
  47.                                 if((dataInfo[1]+1-dataInfo[0]) == dataInfo[2]) startRecvFlag = 1;
  48.                                 else printf("此次接收失败!请重新发送数据!\r\n");
  49.                         }
  50.                 }
  51.                
  52.                 if(startRecvFlag) //开始接收数据
  53.                 {
  54.                         printf("receiving...\r\n");
  55.                         startRecvFlag = 0;
  56.                         startCountRunningTime(); //开始计时
  57.                         for(i=dataInfo[0];i<(dataInfo[1]+1);i++) //循环接收数据
  58.                         {
  59.                                 recvData = receiveData();  //阻塞接收
  60.                                 if(recvData==i) dataBuf[dataCurrentPos++] = recvData;
  61.                                 else
  62.                                 {
  63.                                         if(recvData!=0)
  64.                                         {
  65.                                                 dataCurrentPos = recvData-i;
  66.                                                 dataBuf[dataCurrentPos++] = recvData;
  67.                                                 i = recvData;
  68.                                         }
  69.                                 }                                       
  70.                         }
  71.                         recvTime_us = getRunningTime(); //结束接收计时并得到时间
  72.                         
  73.                         printf("接收完成!正在检验数据……\r\n");  //检验数据
  74.                         dataCurrentPos=0;
  75.                         for(i=dataInfo[0];i<(dataInfo[1]+1);i++)
  76.                         {
  77.                                 if(dataBuf[dataCurrentPos]!=i)
  78.                                 {
  79.                                         errorCounts++;
  80.                                         printf("【err】 ");
  81.                                 }
  82.                                 else printf("%d ",dataBuf[dataCurrentPos]);
  83.                                 dataCurrentPos++;
  84.                         }
  85.                         recvWorkCounts++;
  86.                         printf("\r\n");
  87.                         printf("-----------------------------------------------------\r\n");
  88.                         printf("处理完成!  错误数据: %d 个  总接收用时: %d us (%.3f ms  -->  %.2f s)\r\n", \
  89.                         errorCounts,recvTime_us,(recvTime_us/1000.0),(recvTime_us/1000000.0));
  90.                         printf("-----------------------------------------------------\r\n\r\n");
  91.                         LCD_ShowNum(230,200,recvWorkCounts,9,24);
  92.                         LCD_ShowNum(230,200,errorCounts,9,24);
  93.                         LCD_ShowNum(230,240,recvTime_us,9,24);
  94.                         errorCounts = 0;
  95.                         recvData = 0;
  96.                         dataCurrentPos=0;
  97.                         memset(dataBuf,0,sizeof(dataBuf));
  98.                         printf("等待接收数据……\r\n");
  99.                 }
  100.         }
  101. }
复制代码

原理图: 无
仿真: 无
代码: STM32代码.7z (256.53 KB, 下载次数: 63)

评分

参与人数 1黑币 +100 收起 理由
admin + 100 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:328014 发表于 2020-10-26 14:29 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

板凳
ID:447114 发表于 2021-4-9 10:37 | 只看该作者
问下,有电路原理图可以看下吗
回复

使用道具 举报

地板
ID:554997 发表于 2022-4-8 08:56 | 只看该作者
请问,有原理图吗
回复

使用道具 举报

5#
ID:884711 发表于 2022-9-12 20:49 | 只看该作者
路过留痕,谢谢分享!
回复

使用道具 举报

6#
ID:1097052 发表于 2024-3-19 18:46 | 只看该作者
可以分享一下电路图吗?
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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