基于串口控制的linux无线网连接,并回传当前ip

前言:想法产生

       这个想法是在调试树莓派的时候发生的,因为树莓派作为嵌入式的这么一个平台,尤其在我们安装上ubuntu-mate这一类带桌面系统之后,我们仍需要连接一块屏幕来配置它的网络,很麻烦,所以就想着用ap热点什么的可以直接配网该多好。所有人思维应该是利用ap热点来控制WiFi的连接,当然这也是正常思维才对。但是树莓派这么一个小东西,它的底层简直太脆弱了,底层配置错误轻则无法联网,重则连机都开不了。而ap这么一个重量型工具,需要我们修改更多的底层来配合它完成联网,很无耐。所以在这之后就在想,我们可不可以在应用层通过串口传输账号密码、shell脚本控制来完成联网,我们就可以不用每次换场地联网都要连接一个邋遢的桌面。

一、功能概述

1、硬件连接:通过两个转串模块将pc和树莓派连接起来即可,最好在树莓派端不要连接其他同种类型芯片usb模块,因为我们会指定某一端口来作为接收串口数据端口。如果实在需要,那么下一篇文章我会讲解给Ubuntu增设串口别名的方法。

2、控制流程:Ubuntu端首先启动shell脚本,用于等待接收串口数据;windows端的串口助手,发送账号和密码(空格作为标识符,所以wifi账号和密码都不能出现空格),为了避免串口刚开始接收数据不稳定,所以我们需要手动发送两次数据,连接开始。

二、注意事项

       由于大家在看教程的时候只看教程前面的资料,到了代码这里直接把代码一复制就完事不再往下看了,我也这样,所以我把注意事项写在这里。

       1、此代码只是提供学习使用,并不完善,甚至显得很蹩脚,虽然完成日常事项已经足够,但我确实是用了最笨的实现方法,好多脚本读取文件问题我并没有深究,所以等会儿你会发现我会有三个文本文档,其实一个足够,欢迎大家完善后交流学习。

       2、现在代码的报错机制还不完善,比如wifi不在区域内无报错,没有密码错误报错,但是如果一直没有连接上wifi,一定是这两种错误其中之一。所以为了能准确无误连接wifi,首先用手机测试一下有没有此wifi,密码对不对。

       3、空格为账号和密码标识符、\r\n为结尾标识符,咱们账号密码不要出现空格和\r\n。

       4、我给的文件里文本文档不要删

       5、开机之前首先把硬件连接好

       6、shell脚本没有循环,连接一次不管成功与否,程序都已执行完

现在就想到这些,后期再补

三、代码

提醒大家一下,最后有流程,按照流程来你会成功的

1、c++读取串口数据(serial1.cpp)

#include <iostream>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <cstring>
using namespace std;
int Error_time=0;//用于记录错误次数
int i,i1;
int rec_time=0;//用于记录接收次数
int acc_cri=1;//允许死循环标志位
int rr_num=0;//用于接收来自串口的数据
FILE* NAME1;//分别为用户名和密码
FILE* PASSWORD1;
FILE* ERROR1;
int main(int argc, char **argv)
{
    int fd,flag,wr_num=0;
    struct termios options, newstate;
    speed_t baud_rate_i,baud_rate_o;
    unsigned char buf[40]="Connecting...\r\n\r\n"; //向串口发送的数组
    unsigned char buf1[100];
	unsigned char buf2[20];
	unsigned char buf3[20]="OK.....\r\n\r\n";
	unsigned char error[40]="Error:case 1\r\n\r\n";
    fd=open("/dev/ttyUSB0", O_RDWR|O_NONBLOCK|O_NOCTTY|O_NDELAY);	//打开串口
    if(fd==-1)
          printf("can not open the COM1!\n");
    else
          printf("open COM1 ok!\n");
    
    /*判断是否是终端设备
    if(isatty(STDIN_FILENO) == 0)
      printf("不是终端设备\n");
    else
      printf("是终端设备\n");
    */
   if( fcntl(fd, F_SETFL, 0) <0 ) //改为阻塞模式
      printf("fcntl failed\n");
    else
      printf("fcntl=%d\n", fcntl(fd, F_SETFL, 0));
    
    tcgetattr(fd, &options);

    //设置波特率
    cfsetispeed(&options, B115200);
    cfsetospeed(&options, B115200);
    
    //获取波特率
    tcgetattr(fd, &newstate);
    baud_rate_i=cfgetispeed(&newstate);
    baud_rate_o=cfgetospeed(&newstate);

    //串口设置
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB;//设置无奇偶校验位,
    options.c_cflag &= ~CSTOPB; //设置停止位1
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8; //设置数据位
    options.c_cc[VTIME]=0;//阻塞模式的设置
    options.c_cc[VMIN]=1;

    //激活新配置
    tcsetattr(fd, TCSANOW, &options);
    //输出波特率
    printf("输入波特率为%d,输出波特率为%d\n" , baud_rate_i, baud_rate_o);
    //写入串口
    
   wr_num=write(fd,buf3,sizeof(buf3));
  while(acc_cri)
  {
    int WENJIAN_Flag=0;
    rr_num=read(fd,buf1,sizeof(buf1));
    
     //printf("%d\r\n",rr_num);
  if(rr_num>1)
    {
      rec_time++;
      NAME1 = fopen("NAME.txt", "w");//打开姓名和密码文件
      PASSWORD1 = fopen("PASSWORD.txt", "w");
      for(i=0;i<rr_num;i++)//循环读取并储存在数组
      {
        //printf("%c\r\n",buf1[i]);
        printf("外:%d\r\n",WENJIAN_Flag);
        if(32 == buf1[i])//接收到空格
        {
          //printf("iiiii\r\n");
          WENJIAN_Flag+=1;
          printf("内:%d\r\n",WENJIAN_Flag);
          continue;
        }
        if(WENJIAN_Flag==0)fprintf(NAME1, "%c", buf1[i]);//未接收到空格的动作
        else if(WENJIAN_Flag==1)//接收到空格的动作
		{
			fprintf(PASSWORD1, "%c", buf1[i]); 		
		}
        else //接收到两次空格
        {
			rec_time=3;
			Error_time=1;
        }
      }
      fclose(NAME1);//关闭
      fclose(PASSWORD1);
      if(rec_time>=2)
      {
        
        acc_cri=0;//接收2次程序结束
		if(0==Error_time)
		{
			printf("程序正常结束储存完毕\r\n");
			write(fd,buf,sizeof(buf));
		}
		if(1==Error_time)
		{
			printf("Error 1\r\n"); //接收到两次空格报错
			write(fd,error,sizeof(error));
			ERROR1 = fopen("ERROR.txt", "w");//用于储存错误
			fprintf(ERROR1, "%c", buf2[0]);
			fclose(ERROR1);
		}
      }
    }
  }

    return 0;
}

2、shell 脚本连接无线网主体代码(autoaccwifi.sh)

#!/bin/bash
cd ~/test
./serial1
test="NAME.txt"
test1="ERROR.txt"
time=0;
flag=1;
#若文档为空,则在while循环内等待实际上这样的话,程序已经死了
while [ -e $test -a ! -s $test ]
do
	sleep 1
	echo "wait...$time"
	let time++
	#echo $time
done

if [ -e $test1 -a ! -s $test1 ];then
	flag=0
fi
sed -i '1d' ERROR.txt
echo "已删除错误标志位"
echo $flag
echo "正在接收..."
#此处由于串口最初接收数据不稳定,延时3s接收
sleep 3
for name in `cat NAME.txt`
do
 echo $name
done
for password in `cat PASSWORD.txt`
do
 echo $password
done
echo "接收完毕"
#获取帐号和密码
if (( $flag==0 ));then
	nmcli d wifi connect $name password $password
fi
#删除帐号和密码
sed -i '1d' NAME.txt
sed -i '1d' PASSWORD.txt
echo "已删除账户和密码"
#获取IP地址并以文本形式保存到本地
if (( $flag==0 ));then
	IP=`ifconfig | grep "inet addr" | grep -v 127.0.0.1 | awk '{print}'`
	echo ${IP}
	sh -c "echo ${IP} > autogainip"
fi
./trx

sed -i '1d' autogainip
echo "已删除储存的ip"




3、c++发送当前ip到windows端(trx.cpp)

#include <iostream>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <cstring>
#include <fstream>
#include <cassert>
using namespace std;
int i;
int spa_time=0;//用于记录space
int trx_time=0;//用于记录
int rec_time=0;//用于记录接收次数
int acc_cri=1;//允许死循环标志位
int rr_num=0;//用于接收来自串口的数据



int main(int argc, char **argv)
{
    int fd,flag,wr_num=0;
    struct termios options, newstate;
    speed_t baud_rate_i,baud_rate_o;
    unsigned char buf[40]={}; //向串口发送的数组
    unsigned char buf1[100];
    fd=open("/dev/ttyUSB0", O_RDWR|O_NONBLOCK|O_NOCTTY|O_NDELAY);	//打开串口
    if(fd==-1)
          printf("can not open the COM1!\n");
    else
          printf("open COM1 ok!\n");
    
    /*判断是否是终端设备
    if(isatty(STDIN_FILENO) == 0)
      printf("不是终端设备\n");
    else
      printf("是终端设备\n");
    */
   if( fcntl(fd, F_SETFL, 0) <0 ) //改为阻塞模式
      printf("fcntl failed\n");
    else
      printf("fcntl=%d\n", fcntl(fd, F_SETFL, 0));
    
    tcgetattr(fd, &options);

    //设置波特率
    cfsetispeed(&options, B115200);
    cfsetospeed(&options, B115200);
    
    //获取波特率
    tcgetattr(fd, &newstate);
    baud_rate_i=cfgetispeed(&newstate);
    baud_rate_o=cfgetospeed(&newstate);

    //串口设置
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB;//设置无奇偶校验位,N
    options.c_cflag &= ~CSTOPB; //设置停止位1
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8; //设置数据位
    options.c_cc[VTIME]=0;//阻塞模式的设置
    options.c_cc[VMIN]=1;

    //激活新配置
    tcsetattr(fd, TCSANOW, &options);
    //输出波特率
    printf("输入波特率为%d,输出波特率为%d\n" , baud_rate_i, baud_rate_o);
  while(acc_cri)
  {
	i=0;
    //readTxt("autogainip");
    ifstream infile; 
	string file="autogainip";
    infile.open(file.data());   //将文件流对象与文件连接起来 
    assert(infile.is_open());   //若失败,则输出错误消息,并终止程序运行 

    char c;
    infile >> noskipws;
	while(acc_cri)
	{
		while (!infile.eof())
		{
		    infile>>c;
			if(c==32)spa_time++;
		    if(spa_time<2)
			{
				//cout<<c;
				buf[i]=c;
				//cout<<buf[i];
				if(105 == buf[0])acc_cri=0;
				i++;
			}
			
			//for(i=0;i<wr_num;i++)
		}
	}
	wr_num=write(fd,buf,sizeof(buf));
	
	//for(i=0;i<)
	cout<<endl;
    infile.close();             //关闭文件输入流 
    return 0;
}
}

四、配置流程

1、在home创建一个test文件夹

2、进入test,创建储存代码文件。shell脚本命名为autoaccwifi.sh,c++接收串口代码命名为serial1.cpp,c++发送代码命名为trx.cpp。其实命名是依据你自己的喜好来的,但实际上是牵一发动全身,你熟悉这个代码之后随意更改。

3、创建如图所示文本,拓展名不可随意更改,你熟悉了之后可以在代码中随意配置

4、编译c++代码,g++ serial1.cpp -o serial1和g++ trx.cpp -o trx

5、测试:硬件连接上,终端进入test,执行./autoaccwifi.sh;windows端串口助手发送两次账号和密码,账号和密码以空格为间距。

6、加入到开机选项。我是这样想的,既然我们打算是在应用层实现功能,那我们就不要去打扰底层了,所以开机选项我们这样添加。首先安装gnome:sudo apt install gnome-session-bin;然后启动:gnome-session-properties,添加autoaccwifi.sh路径即可。

<think>好的,我现在需要处理用户关于ADRV9025和Xilinx FPGA集成实现方案及技术文档的查询。首先,我得确认用户的具体需求。用户可能正在开发一个需要集成ADRV9025射频收发器和Xilinx FPGA的系统,比如无线通信设备或雷达系统。他们可能需要硬件设计指南、参考设计、驱动开发支持以及相关的技术文档。 首先,我应该回顾一下ADRV9025的基本信息。ADRV9025是ADI公司的高性能射频收发器,支持多频段,适用于5G、微波回传等应用。Xilinx FPGA,特别是Zynq UltraScale+系列,常被用于这类系统的基带处理。因此,集成方案可能涉及两者的硬件连接、数据接口配置以及软件驱动开发。 接下来,我需要考虑用户可能需要哪些技术资料。硬件方面,参考设计原理图、PCB布局指南、信号完整性分析是关键。软件方面,FPGA的HDL代码示例、JESD204B接口配置、以及ADI提供的Linux驱动和API文档可能都是需要的。此外,技术文档如用户手册、应用笔记以及设计指南也是重要的参考资料。 用户的问题中提到“实现方案”,这可能包括评估板的使用、接口配置步骤、时钟同步方法等。例如,ADRV9025通过JESD204B/C接口与FPGA通信,需要确保FPGA支持相应的IP核,且时钟树设计合理以避免同步问题。此外,电源管理和散热设计也是集成时需要考虑的因素。 我还需要检查是否有相关的官方资源。ADI和Xilinx的官方网站应该提供了大量的应用笔记和参考设计。比如,ADI的Wiki页面可能有ADRV9025的详细资料,而Xilinx的JESD204 IP核文档对于接口实现至关重要。同时,用户可能需要参考第三方社区或论坛,如Xilinx Support和ADI EngineerZone,以获取实际项目中的经验分享和问题解决方案。 考虑到用户之前提到的技术文档需求,如硬件使用说明书、原理图、管脚定义表等,我需要确保回答中包含获取这些文档的途径。例如,ADI通常会提供评估板的用户指南和原理图,而Xilinx则有FPGA开发板的详细资料。 最后,生成相关问题时,要围绕用户可能遇到的后续挑战,如时钟管理、接口调试、驱动开发、系统集成测试等。这些问题能够帮助用户进一步深入解决实际开发中的具体问题。 总结一下,回答的结构应包括硬件集成方案、软件配置、技术文档资源,以及常见问题的解决方案,附上相关问题引导用户深入探讨具体技术细节。</think>关于ADRV9025与Xilinx FPGA集成实现方案,以下是技术要点和资料获取途径: ### 一、硬件集成方案 1. **接口设计** - JESD204B/C高速串行接口实现基带数据交互,需配置$Lane\ Rate = 9.84Gbps$时达到最大带宽 - 参考ADI提供的$ADRV9025-EVALZ$评估板原理图进行信号完整性设计[^1] 2. **时钟架构** $$ f_{REFCLK} = 122.88MHz \quad (需满足\pm1ppm精度) $$ 推荐使用Xilinx GTY收发器的Quad-based PLL架构 3. **电源设计** - 采用多相PMIC方案满足1.0V/3.3V/1.8V电源轨 - 特别注意$AVDD\_TX/RX$需要<3mV纹波 ### 二、软件配置流程 1. **FPGA工程配置** ```tcl create_ip -name jesd204 -vendor xilinx.com -library ip -version 7.0 \ -module_name jesd204_0 set_property CONFIG.C_LANE_RATE {9.84} [get_ips jesd204_0] ``` 2. **ADI Linux驱动集成** ```bash git clone https://github.com/analogdevicesinc/linux make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- adi_zynqmp_defconfig ``` ### 三、关键文档资源 | 文档类型 | 获取途径 | |---------|----------| | ADRV9025硬件设计指南 | Analog Devices官网[^1] | | JESD204 IP核配置手册 | Xilinx DocNav工具 | | 参考设计工程包 | ADI GitHub仓库(需NDA) | | 信号完整性报告 | 评估板附带资料[^1] | ### 四、典型问题解决方案 1. **JESD链路失锁** - 检查$SYNC~$信号时序满足$t_{setup}>1.5ns$ - 验证SYSREF与DEVCLK相位关系满足$$ |\Delta\phi| < \frac{1}{4f_{SYSREF}} $$ 2. **射频性能优化** - 采用Xilinx IBERT进行眼图测试 - 调整$FFE_{PRE}/MAIN$参数使$BER<10^{-12}$
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值