O_LinuxQT_ARM开发初试水
O_嵌入式专题目录
项目开始于2018.6.20;结束于2018.7.10。
PC端为Ubuntu下的QT4及arm-linux-gcc交叉编译环境,ARM为ARM9的官方FriendlyARM实验箱及配套软件系统。
一、交叉编译环境
1.解压安装
tar xvzf arm-linux-gcc-4.5.1-v6-vfp-20101103.tgz –C/ 注意:C 后面有个空格,并且 C 是大写的,它是英文单词“Change”的第一个字母,在此 是改变目录的意思。
执行该命令,将把 arm-linux-gcc 安装到/opt/FriendlyARM/toolschain/4.5.1 目录。
2.把编译器路径加入系统环境变量
gedit /root/.bashrc编辑/root/.bashrc 文件,修改最后一行为
export PATH=$PATH:/opt/FriendlyARM/toolschain/4.5.1/bin保存退出,重新登录系统,使以上设置生效,在命令行输入
arm-linux-gcc –v会出现版本信息,这说明交叉编译环境已经成功安装。
二、Linux下Qt4的安装
1.Qt源码及QtCreater下载
Qt4.8.6源码:
http://download.qt.io/official_releases/qt/4.8/4.8.6/
下载【qt-everywhere-opensource-src-4.8.6.tar.gz】。
QtCreator4.0.3
http://download.qt.io/official_releases/qtcreator/4.0/4.0.3/
下载【qt-creator-opensource-linux-x86_64-4.0.3.run】。
2.安装QtCreator4.0.3
./qt-creator-opensource-linux-x86_64-4.0.3.run
提示:输入前几个字符后按下tab可快捷补全文件名进入QtCreator安装界面,指定安装位置,然后就是按照提示一直到安装结束。
提示:若提示
sudo: unable to execute ./qt-creator-opensource-linux-x86_64-4.0.3.run: 没有那个文件或目录首先确认你在输入指令的目录下确实有这个文件,若确认有还提示错误的话,大概是因为那个.run文件没有“执行”属性,执行以下命令再试试:
chmod +x qt-creator-opensource-linux-x86_64-4.0.3.run3.安装Qt4.8.6
a.解压
tar xzvf qt-everywhere-opensource-src-4.8.6.tar.gzb.进入目录配置
cd ./qt-everywhere-opensource-src-4.8.6
./configure 输入c回车,表示使用社区版。
输入o回车,表示使用开源版。
然后输入yes回车,表示同意协议。
提示:若提示
Basic XLib functionality test failed!
You might need to modify the include and library search paths by editing QMAKE_INCDIR_X11 and QMAKE_LIBDIR_X11 in /home/usr/local/qt/mkspecs/linux-g++是因为缺少libX11的开发包,根据自己的系统特点,安装 libX11-dev libXext-dev libXtst-dev
apt-get install libX*
//或
apt-get install libX11-dev libXext-dev libXtst-devc.编译
make一般需要1-2小时甚至更久,一定要有耐心呦。
d.安装
make install默认安装/usr/local/Trolltech/目录下。
提示:若在make阶段出现
/usr/bin/ld: cannot find -lXrender
collect2: ld returned 1 exit status
make[1]: *** [../../../../lib/libQtWebKit.so.4.7.3] 错误 1
make[1]: Leaving directory `/home/dowload/qt-everywhere-opensource-src-4.7.3/src/3rdparty/webkit/WebCore'
make: *** [sub-webkit-make_default-ordered] 错误 2 是因为没有装libxrender-dev,用apt-get安装即可。
若提示
Makefile:xxx: recipe for target xxx failed 等 可以在make及make install后面加上“-i”,即ignore忽略掉错误继续编译。
详情见:如何忽略makefile执行过程中的某些命令的错误而得以继续运行
e.设置环境变量
gedit /root/.bashrc在最后一行添加并保存:
export QTDIR=/usr/local/Trolltech/Qt-4.8.6
export PATH=$QTDIR/bin:$PATH
export MANPATH=$QTDIR/man:$MANPAT
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATHf.测试
qmake -v
提示:
QMake version 2.01a
Using Qt version 4.8.6 in /usr/local/Trolltech/Qt-4.8.6/lib安装完成。
3.Qt4.8.6+QtCreator4.0.3配置
第一步:tools>options>Build and Run,然后选择Qt Versions,点击 Browse 选择刚才安装的Qt库,然后点击应用。
第二步:选择Kits,手动添加一个,GCC,GDB会自动检测,这里需要指定Qt Version,默认是None,选择我们刚才添加的Qt 4.8.6。
安装过程参考自:linux上安装Qt4.8.6+QtCreator4.0.3
三、Linux下Qt5的安装
1.Qt源码及QtCreater下载
Qt4.8.6源码:
http://download.qt.io/official_releases/qt/5.6/5.6.2/
下载【qt-opensource-linux-x64-5.6.2.run】。
QtCreator4.0.3
http://download.qt.io/official_releases/qtcreator/4.6/4.6.2/
下载【qt-creator-opensource-linux-x86_64-4.6.2.run】。
2.安装
找到两个.run文件双击运行或用终端运行即可。
3.配置
与QT4相同,QT库文件在QT5.6.2->QT5.6->gcc_64->bin->qmake。
四、Qt开发项目基本界面
界面如图:

各控件名称及分组:

1. radioButton&buttonGroup
a.QtCreater建立buttonGroup
选中多个button,右键,指定到按钮组。(建议一个box建立一个组)
b.获取选中的radioButton
方法一:采用对象名称进行获取
详见:动态取得控件的objectName之后,对名字进行比较
方法二:通过button的ID来获取
对于已经设置在buttonGroup中的button
ui->buttonGroupA->setId(ui->radioButton0, 0);
ui->buttonGroupA->setId(ui->radioButton1, 1);
ui->buttonGroupA->setId(ui->radioButton2, 2);
...对于未添加到buttonGroup的button
buttonGroupA->addButton( ui.radioButton0, 0 );
buttonGroupA->addButton( ui.radioButton1, 1 );
buttonGroupA->addButton( ui.radioButton2, 2 );
...之后就可以在connect中将选中的buttonID传到槽函数中,在槽函数中便可判断按键了。
connect( buttonGroupA, SIGNAL(buttonClicked (int)), this, SLOT(buttonChose(int)) );//连接信号和槽2. QLCDNumber
显示数字:
ui->LCD1->display(要显示的数字或变量);常用接口:
setDigitCount(int numDigits)设置所显示的位数
setBinMode()以二进制形式显示
setOctMode()以八进制形式显示
setHexMode()以十六进制形式显示
setDecMode()以十进制形式显示(默认)简易时钟示例:
void onTimeOut()
{
// 获取系统当前时间
QDateTime dateTime = QDateTime::currentDateTime();
// 显示的内容
m_pLCD->display(dateTime.toString("yyyy-MM-dd HH:mm:ss.zzz"));
}3. textBrowser
添加文字:
ui->textBrowserA->setText(tmp);
//或
ui->textBrowserA->textCursor().insertText(tmp);//插入文本到光标位置4. QString与int类型转换
QString转int:toInt()
例:
QString str("100");
int tmp = str.toInt();或者:
bool ok;
QString str("100");
int tmp = str.toInt(&ok);
注:ok表示转换是否成功,成功则ok为true,失败则ok为false。int转QString
例:
int tmp = 100;
QString str = QString::number(tmp);5. 添加图片
添加图片资源
a.右键工程,添加新文件
b.左边选择QT,右边选择qt资源文件
c.选择文件路径,自己命名资源名,下一步
d.完成之后,就可以看到有一个qrc后缀名的文件,那就是你的资源文件夹了
c.点击添加前缀,再点击添加文件
使背景图自动调整来适应控件的大小
推荐使用border-image。
默认background-image 不会缩放图片以适应控件的大小。
如果要提供一个皮肤或背景图片以自动适应控件大小,必须也只能用border-image属性。
因为border-image已经设置了可用的背景图片,所以使用了border-image后,没必要再指定background-image。
如果同时指定了两个属性,那么将会使用border-image 绘制覆盖掉background-image。
6. 调用可执行程序及终端命令
头文件添加stdlib.h
system("./pc 192.1.1.1 2W401013");或
头文件添加QProcess
QProcess sys;
QString output;
sys.start("./pc 192.168.1.230 2R000003");
sys.waitForFinished();
output=sys.readAllStandardOutput();//读取传回的所有字符7. 对字符串进行操作
a.使某个字符填满字符串
也就是说字符串里的所有字符都有等长度的ch来代替。
QString::fill ( QChar ch, int size = -1 )例如:
QString str = "Berlin";
str.fill('z'); // str == "zzzzzz" str.fill('A', 2); // str == "AA"b.从字符串查找相同的字符串
int QString::indexOf ( const QString & str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive ) const例如:
QString x = "sticky question";
QString y = "sti";
x.indexOf(y); // returns 0 x.indexOf(y, 1); // returns 10 x.indexOf(y, 10); // returns 10 x.indexOf(y, 11); // returns -1c.指定位置插入字符串
QString & QString::insert ( int position, const QString & str )例如:
QString str = "Meal";
str.insert(1, QString("ontr")); // str == "Montreal"d.判断字符串是否为空
bool QString::isEmpty () const例如:
QString().isEmpty(); // returns true QString("").isEmpty(); // returns true QString("x").isEmpty(); // returns false QString("abc").isEmpty(); // returns falsee.判断字符串是否存在
bool QString::isNull () const例如:
QString().isNull(); // returns true QString("").isNull(); // returns false QString("abc").isNull(); // returns falsef.从左向右截取字符串
QString QString::left ( int n ) const例如:
QString x = "Pineapple";
QString y = x.left(4); // y == "Pine"g.从中间截取字符串
QString QString::mid ( int position, int n = -1 ) const例如:
QString x = "Nine pineapples";
QString y = x.mid(5, 4); // y == "pine" QString z = x.mid(5); // z == "pineapples"h.删除字符串中间某个字符
QString & QString::remove ( int position, int n )例如:
QString s = "Montreal";
s.remove(1, 4); // s == "Meal"i.替换字符串中的某些字符
QString & QString::replace ( int position, int n, const QString & after )例如:
QString x = "Say yes!";
QString y = "no";
x.replace(4, 3, y); // x == "Say no!"j.以某个字符切割字符串
QString QString::section ( QChar sep, int start, int end = -1, SectionFlags flags = SectionDefault ) const例如:
QString str;
QString csv = "forename,middlename,surname,phone";
QString path = "/usr/local/bin/myapp"; // First field is empty QString::SectionFlag flag = QString::SectionSkipEmpty;
str = csv.section(',', 2, 2); // str == "surname" str = path.section('/', 3, 4); // str == "bin/myapp" str = path.section('/', 3, 3, flag); // str == "myapp"k.其他类型转为QString
QString & QString::setNum ( uint n, int base = 10 )l.
如果我们希望检查一个字符串是否是以某物开始或结束,我们可以使用startsWith()和endsWith()函数:
if (url.startsWith("http:") && url.endsWith(".png"))...这个要比下面的简单快速:
if (url.left(5) == "http:" && url.right(4) == ".png")... 使用==操作符的字符串比较是大小写敏感的。
如果我们正在比较用户级(user-visible)字符串,localeAwareCompare()经常是正确的选择,并且如果我们希望大小写不敏感,我们可以用toUpper()或toLower()。
例如:
if (fileName.toLower() == "readme.txt")...8. 测试PC与ARM正常通信
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
int main()
{
int fd,led;
char buf[100];
int i=0;
led=open("/dev/leds",O_RDONLY);
if(led<0) exit(1);
fd=open("/dev/adc",O_RDWR);
if(fd<0) exit(1);
while(1)
{
i=read(fd,buf,sizeof(buf)-1);
buf[i]='\0';
sscanf(buf,"%d",&i);
printf("AD=%d\n",i);
sleep(1);
ioctl(led,0,0);//LED control (file,on/off,adress)
}
close(fd);
close(led);
return 0;
}
9. socket通信及TCP协议通信源码
PC端
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define SERVPORT 3333
#define MAXDATASIZE 100
main(int argc,char *argv[])
{
int sockfd,client_fd,client_sockaddr,sendbytes,recvbytes;
int adc,len;
char buf[MAXDATASIZE],buffer[32];
struct hostent *host;
struct sockaddr_in serv_addr;
if(argc<2)
{
fprintf(stderr,"Please enter the server's hostname!\n");
exit(1);
}
if((host=gethostbyname(argv[1]))==NULL)
{
perror("gethostbyname");
exit(1);
}
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket");
exit(1);
}
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERVPORT);
serv_addr.sin_addr=*((struct in_addr *)host->h_addr);
bzero(&(serv_addr.sin_zero),8);
if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr))==-1)
{
perror("connect");
exit(1);
}
if((sendbytes=send(sockfd,argv[2],8,0))==-1)
{
perror("send");
exit(1);
}
/*if((client_fd=accept(sockfd,(struct sockaddr *)&client_sockaddr,&sin_size))==-1)
{
perror("accept");
exit(1);
}
printf("accept success\n");*/
if(argv[2][1]=='R')
{
if((recvbytes=recv(sockfd,buffer,MAXDATASIZE,0))>0)
{
buffer[recvbytes]='\0';
printf("%s\n",buffer);
}
//printf("open adc\n");
}
else if(argv[2][1]=='W')
{
printf("open led\n");
}
close(sockfd);
}
ARM端
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#define SERVPORT 3333
#define BACKLOG 10
#define MAX_CONNECTED_NO 10
#define MAXDATASIZE 64
static char RcvBuf[100];
static char SendBuf[100];
int main()
{
struct sockaddr_in server_sockaddr,client_sockaddr;
int sin_size,recvbytes;
int sockfd,client_fd;
char buf[MAXDATASIZE];
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket");
exit(1);
}
printf("socket success! sockfd=%d\n",sockfd);
server_sockaddr.sin_family=AF_INET;
server_sockaddr.sin_port=htons(SERVPORT);
server_sockaddr.sin_addr.s_addr=INADDR_ANY;
bzero(&(server_sockaddr.sin_zero),8);
if(bind(sockfd,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr))==-1)
{
perror("bind");
exit(1);
}
printf("bind success!\n");
if(listen(sockfd,BACKLOG)==-1)
{
perror("listen");
exit(1);
}
printf("listen success\n");
if((client_fd=accept(sockfd,(struct sockaddr *)&client_sockaddr,&sin_size))==-1)
{
perror("accept");
exit(1);
}
printf("accept success\n");
while(1)
{
if((recvbytes=recv(client_fd,buf,MAXDATASIZE,0))>0)
{
buf[recvbytes]='\0';
printf("Receive:%s\n",buf);
HandleTCP(buf,recvbytes);
//printf("222\n");
send(client_fd,SendBuf,8,0);
//printf("333\n");
}
else if(recvbytes<=0)
{
printf("Connection closed!\n");
close(client_fd);
client_fd=accept(sockfd,(struct sockaddr *)&client_sockaddr,&sin_size);
}
}
close(sockfd);
}
void HandleTCP(char *bf,int len)
{
int i,RcvPtr=0;
for(i=0;i<len;i++)
{
if(*(bf+i)=='2')
{
//printf("b1\n");
RcvBuf[0]='2';
RcvPtr=1;
}
else if(*(bf+i)=='3')
{
//printf("c1\n");
if(RcvPtr==7) ParseFrame();
//printf("c1end\n");
RcvPtr=0;
}
else
{
//printf("ptr %d\n",RcvPtr);
if(RcvPtr>0) RcvBuf[RcvPtr++]=*(bf+i);
//printf("bf i %c\n",*(bf+i));
}
}
}
void ParseFrame()
{
int adc,led;
int d,len;
char buffer[32];
SendBuf[0]='2';
if(RcvBuf[1]=='R')
{
SendBuf[1]='B';
SendBuf[2]=RcvBuf[2];
switch(RcvBuf[2])
{
case '0':
adc=open("/dev/adc",0);
if(adc<0) SendBuf[1]='E';
else
{
len=read(adc,buffer,sizeof(buffer)-1);
sscanf(buffer,"%d",&d);
sprintf(&SendBuf[3],"%04d",d);
close(adc);
}
SendBuf[7]='3';
break;
case '1':
adc=open("/dev/adc",1);
if(adc<0) SendBuf[1]='E';
else
{
len=read(adc,buffer,sizeof(buffer)-1);
sscanf(buffer,"%d",&d);
sprintf(&SendBuf[3],"%04d",d);
close(adc);
}
SendBuf[7]='3';
break;
case '2':
adc=open("/dev/adc",2);
if(adc<0) SendBuf[1]='E';
else
{
len=read(adc,buffer,sizeof(buffer)-1);
sscanf(buffer,"%d",&d);
sprintf(&SendBuf[3],"%04d",d);
close(adc);
}
SendBuf[7]='3';
break;
case '3':
adc=open("/dev/adc",3);
if(adc<0) SendBuf[1]='E';
else
{
len=read(adc,buffer,sizeof(buffer)-1);
sscanf(buffer,"%d",&d);
sprintf(&SendBuf[3],"%04d",d);
close(adc);
}
SendBuf[7]='3';
break;
}
}
else if(RcvBuf[1]=='W')
{
if(RcvBuf[2]=='4')
{
led=open("/dev/leds",O_RDONLY);
//RcvBuf[6]-0x30;
if(RcvBuf[3]=='1') ioctl(led,0,3);
else if(RcvBuf[3]=='0') ioctl(led,1,3);
if(RcvBuf[4]=='1') ioctl(led,0,2);
else if(RcvBuf[4]=='0') ioctl(led,1,2);
if(RcvBuf[5]=='1') ioctl(led,0,1);
else if(RcvBuf[6]=='0') ioctl(led,1,1);
if(RcvBuf[6]=='1') ioctl(led,0,0);
else if(RcvBuf[6]=='0') ioctl(led,1,0);
close(led);
}
}
}
10.QT界面代码
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QDebug"
#include "QProcess"
MainWindow::MainWindow(QWidget *parent):
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setButtonId();
connect(ui->levelGroup,SIGNAL(buttonClicked(int)),this,SLOT(levelChose(int)));
connect(ui->funcGroup,SIGNAL(buttonClicked(int)),this,SLOT(funcChose(int)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::setButtonId()
{
ui->levelGroup->setId(ui->level1,1);
ui->levelGroup->setId(ui->level2,2);
ui->levelGroup->setId(ui->level3,3);
ui->levelGroup->setId(ui->level4,4);
ui->levelGroup->setId(ui->level5,5);
ui->levelGroup->setId(ui->level6,6);
ui->levelGroup->setId(ui->level7,7);
ui->levelGroup->setId(ui->levelAuto,8);
//qDebug()<<levelNumber;
levelNumber=8;
//qDebug()<<levelNumber;
ui->ADCshow->setEnabled(false);
ui->funcGroup->setId(ui->levelChoseButton,0);
ui->funcGroup->setId(ui->ADC0,10);
ui->funcGroup->setId(ui->ADC1,11);
ui->funcGroup->setId(ui->ADC2,12);
ui->funcGroup->setId(ui->ADC3,13);
//qDebug()<<funcNumber;
funcNumber=0;
//qDebug()<<funcNumber;
}
void MainWindow::levelShow()
{
ui->lcdLevelNumber->display(levelNumber);
}
void MainWindow::levelChose(int levelTT)
{
levelNumber=levelTT;//ui->levelGroup->checkedId();
//qDebug()<<levelNumber;
levelShow();
TCP(levelNumber);
}
void MainWindow::funcChose(int funcTT)
{
funcNumber=funcTT;
//qDebug()<<funcNumber;
if(funcNumber==0)
{
ui->levelBox->setEnabled(true);
ui->ADCshow->setEnabled(false);
ADC_Data(0);
}
else if(funcNumber==10)
{
ui->ADCshow->setEnabled(true);
ui->levelBox->setEnabled(false);
ADC_Data(0);
ADC_Data(10);
}
else if(funcNumber==11)
{
ui->ADCshow->setEnabled(true);
ui->levelBox->setEnabled(false);
ADC_Data(0);
ADC_Data(11);
}
else if(funcNumber==12)
{
ui->ADCshow->setEnabled(true);
ui->levelBox->setEnabled(false);
ADC_Data(0);
ADC_Data(12);
}
else if(funcNumber==13)
{
ui->ADCshow->setEnabled(true);
ui->levelBox->setEnabled(false);
ADC_Data(0);
ADC_Data(13);
}
}
void MainWindow::ADC_Data(int ADCTT)
{
switch (ADCTT) {
case 0:
ui->ADCtext->clear();
break;
/*case 10:
for(int i=0;i<10;i++)
ui->ADCtext->textCursor().insertText("ADC=0000"+QString::number(i)+"\n");
break;
case 11:
for(int i=0;i<10;i++)
ui->ADCtext->textCursor().insertText("ADC=1100"+QString::number(i)+"\n");
break;
case 12:
for(int i=0;i<10;i++)
ui->ADCtext->textCursor().insertText("ADC=2200"+QString::number(i)+"\n");
break;
case 13:
for(int i=0;i<10;i++)
ui->ADCtext->textCursor().insertText("ADC=3300"+QString::number(i)+"\n");
break;*/
default:
for(int i=0;i<10;i++)
{
QString rTT=TCP(10);
ui->ADCtext->textCursor().insertText(rTT+"\n");
//qDebug()<<rTT;
}
break;
}
}
QString MainWindow::TCP(int sBuf)
{
QString output;
QString rBuf;
QProcess sys;
switch (sBuf) {
case 1:
system("./pc 192.168.1.230 2W411103");
break;
case 2:
system("./pc 192.168.1.230 2W411013");
break;
case 3:
system("./pc 192.168.1.230 2W411003");
break;
case 4:
system("./pc 192.168.1.230 2W410113");
break;
case 5:
system("./pc 192.168.1.230 2W410103");
break;
case 6:
system("./pc 192.168.1.230 2W410013");
break;
case 7:
system("./pc 192.168.1.230 2W410003");
break;
case 8:
system("./pc 192.168.1.230 2W401113");
break;
case 10:
{
sys.start("./pc 192.168.1.230 2R000003");
sys.waitForFinished();
output=sys.readAllStandardOutput();
rBuf=output.mid(3,4);
//qDebug()<<rBuf;
break;
}
default:
break;
}
return rBuf;
}11. 调用程序的编译及上传运行
gcc TCPIP_PC.cpp -o pc
//在PC的Linux上编译TCPIP_PC.cpp,并将编译出的pc文件放到QT编译出的Debug目录下。
arm-linux-gcc TCPIP_ARM.cpp -o arm
//在PC的Linux上用交叉编译TCPIP_ARM.cpp。
ftp 192.168.1.230//此IP为ARM开发板上的IP
//Login...
ftp>put arm
//将编译出的arm可执行文件上传到arm根目录下。
ftp>Bye
//退出ftp
telnet 192.168.1.230
//与ARM开发板的Linux系统进行连接。
./arm
//运行ARM开发板上的arm程序,进行侦听pc的连接。
//之后打开QT界面进行操作及通信。12. ARM开发板上的程序开机启动
在PC上用telnet连接ARM,打开etc/init.d/rcS文件,添加./arm即可。
注:若用gedit打开,添加完直接保存退出即可,若用vi打开,添加完后esc,用:wq保存并退出。
附:vi指令
a.打开文件:
# vi /etc/my.cnf //打开或新建文件,并将光标至于第一行首
# vi + /etc/my.cnf //打开文件,并将光标移至最后一行行首
# vi +n /etc/my.cnf //打开文件,并将光标置于第n行首
# vi +/pattern filename //打开文件,并将光标置于第一个与pattern匹配的串处b.按键盘上“a”键,vi界面出现 INSERT后,开始进行编辑操作
c.编辑完毕后,按ESC键,跳到命令模式,然后进行保存退出或不保存退出操作:
:w //保存,不退出vi
:w! //强制保存,不退出vi
:w file //将修改另外保存到file中,但不退出vi(不常用)
:wq 或 :x //保存,并退出vi
:wq! //强制保存,并退出vi
**d.下面是不保存的相关命令**
:q //不保存,并退出vi
:q! //不保存,并强制退出vi
:e! //放弃所有修改,从上次保存文件开始再编辑13. QSS相关
14. 自动进样器代码
#include <STC89C52RC.h>
//P20-P1.0转盘脉冲
//P21-P1.1转盘方向
//P22-P1.2针臂脉冲
//P23-P1.3针臂方向
//P25-P0.1下限位
//P26-P0.2上限位
//P27-P0.0霍尔传感器
void delay()
{
TMOD=0x01;
TH0=0xac; //Speed
TL0=0xf0;
TF0=0;
TR0=1;
while(TF0==0);
TR0=0;
}
void delayo()
{
int i;
for(i=0;i<2600;i++){}
}
void updown()
{
int i=0;
P23=1;
for(i=0;i<430;i++)
{
P22=1;
delayo();
P22=0;
delayo();
}
P23=0;
for(i=0;i<430;i++)
{
P22=1;
delayo();
P22=0;
delayo();
}
}
void runo()
{
P20=1;
delayo();
P20=0;
delayo();
}
void run()
{
P20=1;
delay();
P20=0;
delay();
}
main()
{
int i;
int fi;
int T24=100;
bit pf=0;
TMOD=0x21;
TH1=0xe8;
TL1=0xe8; //1200波特率12MHz
TR1=1;
SCON=0x50;
TI=1;
while(0)
{
//转盘针臂
if(P27||T24!=0)
{
T24--;
run();
}
if(P27) pf=1;
else if(P27==0)
{
if(pf==1)
{
pf=0;
T24=23;
}
if(pf==0&&T24==0)
{
updown();
T24=8;//goto loop;
}
}
}
//串口通讯
/*for(i=0;i<10;i++)
{
while(TI=0);
TI=0;
SBUF=i; //发送i
}*/
/*if(RI) //接收到字符
{
i=SBUF; //接收i
RI=0; //接收标志位RI
TI=0; //发送结束标志位TI
SBUF=i; //发送i
while(TI==0); //等待发送完毕
}*/
//四位控制
while(1){
loop:if(RI)
{
fi=SBUF;
RI=0;
if(fi==0) //Reset
{
P21=1;
T24=100;
while(1)
{
if(P27||T24!=0)
{
T24--;
runo();
}
if(P27) pf=1;
else if(P27==0)
{
if(pf==1)
{
pf=0;
T24=23;
}
if(pf==0&&T24==0)
{
updown();
T24=8;
if(RI)
goto loop;
}
}
}
}
if(fi==1) //转换转的方向
{
P21=~P21;
while(1)
{
runo();
if(RI)
goto loop;
}
}
if(fi==2) //停止
{
P20=0;
goto loop;
}
if(fi==3) //继续
{
while(1)
{
runo();
if(RI)
goto loop;
}
}
if(fi==4) //抽取
{
P20=0;
updown();
goto loop;
}
}
}
}
评论已关闭