赞
踩
1、Jar包上传到FTP
2、登录Ubuntu,修改jar包的属性sudo chmod 777 xxxxx.jar
3、运行jar nohup java -jar xxxxxx.jar
4、结束服务: ps -e | grep java 查看java的进程号
5、sudo kill 进程号
nohup java -jar /srv/ftpdata/smu/www/shared_device_service-1.0-SNAPSHOT.jar & #后台运行
如果创建一个表头指针后用malloc申请空间,结构体的值为0.
存放一串 地址的 数组。
int a = 2;
int b = 3;
int c = 5;
int* p[3];
p[0] = &a;
p[1] = &b;
p[2] = &c;
1、强调的是类型,数组的个数,偏移值是偏移了整个数组的大小。
2、包住了整个数组的所有地址的指针。该指针++后,地址增加数据类型的个数*数组的大小。
int a[3] = {1,2,3};
int (*p)[3];
p = a;
int fun(int a,int b){ return a+b; } void printWelcome(){ printf("欢迎来到嵌入式攻城狮大课堂!!\n"); } int main(){ int (*pfun)(int data,int data2); pfun = fun; pfun(1,2); (*pfun)(1,2); //---------------------------- void (*p2)(); p2 = printWelcome; p2(); (*p2)(); return 0; }
void* malloc(size_t,size);返回类型是void*,即:无类型的指针;**但可以强制转换(int *)、(char )、(double )…
申请32个字节的空间,这32个字节是连续的,一个整块。
如果要存放整形(int)必须在前面加上(int *),即:(int *)malloc(32);
int XX[3]; //数组
int *p =XX;
int *a = (int *)malloc(3 * sizeof(int));//这也是数组,(* a,* p)两者一样的
1.定义整形变量 a
2.定义p为指向整形数据的指针变量
3.定义整型数组 a,它有5个元素
4.定义指针数组 p,它由4个指向整型数据的指针元素组成
5.p为指向包含4个元素的一堆数组的指针变量
6.f为返回整形函数值的函数
7.p为返回一个指针的函数,该指针指向整型数据
8.p为指向函数的指针,该函数返回一个整型值
9.p是一个指针变量,它指向一个指向整型数据的指针变量
10.p是一个指针变量,基类型为 void(空类型),不指向具体的对象
答案:(1)int a; (2)int *p; (3)int a[5]; (4)int *p[4];指针数组
(5)int (*p)[4];数组指针,跨越的是整个数组,16个字节 (6)int f();
(7)int* p(); (8)int (*p)(); (9)int **p; (10)void *p;
1、char str[5] = {'a','b','c','d','e'};
2、char str[5] = "abcde";
3、char str[] = "abcde";***//长度 (用sizeof()求)= 字符个数 + 1,因为这种方式会在后面默认加上‘\0’。代表字符串的结束标志***
4、用指针定义:char *pstr = "abcdefghijk";
1、printf("%c\n",str[i]);//逐个输出
2、printf("%s\n",pstr);//一次性输出
3、puts(str);//和2一样,只是多了一个自动换行
1、scanf("%s",str);
2、gets(str);
灵活
1、数组的地址是连续的,链表是不连续的。
2、链表只不过是它的next值指向一个地址。
#include <curses.h> //头文件
initscr(); //ncurse界面的初始化函数
printw("This is curses windows\n"); //在ncurse模式下的printf
getch(); //等待用户输入,如果没有这句话,程序就退出了,看不到运行结果,也就是看不到上面那句话
endwin(); //程序退出,调用该函数来恢复shell终端的显示,如果没有这句话,shell终端会乱码,乱结构,坏掉。
#define KEY_DOWN 0402 #define KEY_UP 0403 #define KEY_LEFT 0404 #define KEY_RIGHT 0405 #define KEY_HOME 0406 #define KEY_BACKSPACE 0407 #define KEY_F0 0410 #define KEY_F(n) (KEY_ F0+(n)) #define KEY_DL 0510 #define KEY_IL 0511 int c; initscr(); printw("this is a test\n"); keypad(stdscr,1); while(1){ c = getch(); switch(c){ case KEY_DOWN: printw("DOWN\n"); break; case KEY_UP: printw("UP\n"); break; case KEY_LEFT: printw("LEFT\n"); break; case KEY_RIGHT: printw("RIGHT\n"); break; default : printw("you input :%d\n",c); break; } } getch(); endwin();
void initFood(){
food.hang = rand()%20;
food.lie = rand()%20;
}
int hasFood(int i,int j){
if(food.hang == i && food.lie == j){
return 1;
}
return 0;
}
int hasNode(int i,int j){//判断是否存在该节点
struct Snake *p;
p = head;
while(p != NULL){
if(p->hang == i && p->lie == j){
return 1;
}
p = p-> next;
}
return 0;
}
void initNcurse(){//让键盘之直接取到方向值,即:去掉"^[["
initscr();
keypad(stdscr,1);
}
void gamePic(){//贪吃蛇地图构建 int hang; int lie; move(0,0);//每次让光标移动到最左上角,刷新的时候保证图形一直在固定位置 for (hang = 0;hang < 20;hang ++){ if(hang == 0){ for(lie = 0;lie <= 20;lie ++){ printw("--"); } printw("\n"); for(lie = 0;lie <= 21;lie ++){ if(lie == 0 || lie == 21){ printw("|"); } else if(hasNode(hang,lie)){ printw("[]");//当该坐标(hang,lie)为蛇的身子时,打印出蛇身“[]” } else{ printw(" "); } } printw("\n"); } if(hang > 0 && hang < 20){ for(lie = 0;lie <= 21;lie ++){ if(lie == 0 || lie == 21){ printw("|"); } else if(hasNode(hang,lie)){ printw("[]");//同上 } else{ printw(" "); } } printw("\n"); } if(hang == 19){ for(lie = 0;lie < 21;lie ++){ printw("--"); } printw("\n"); printw("Made by Du Shangkun\n"); } } }
void addNode(){//添加蛇身子
struct Snake *new = (struct Snake *)malloc(sizeof(struct Snake));
new->hang = tail->hang;
new->lie = tail->lie + 1;//默认蛇身子向右移动
tail->next = new;
tail = new;
}
void intSnake(){//蛇的最初位置及长度
head = (struct Snake *)malloc(sizeof( struct Snake));
head->hang = 2;
head->lie = 2;
head->next = NULL;
tail = head;
addNode();
addNode();
addNode();
addNode();
}
void deleNode(){//删除节点用的
//struct Snake *p;
//p = head;
head = head -> next;
//free(p);
}
void moveSnake(){//蛇身子的移动 <=> 添加新的节点,删掉旧的节点
// struct Snake *p;
// struct Snake *new;
addNode();
deleNode();
}
int main(){//主函数 int con;//接受键盘指令 initNcurse(); intSnake(); gamePic(); while(1){ con = getch(); if(con == KEY_RIGHT){//激发右→时 moveSnake(); gamePic(); } } getch(); endwin();//必须要加,不然界面会乱掉 return 0; }
# include <Servo.h> # define Echo D2 # define Trig D8 # define DuoPIN D4 # define BEEF D3 Servo myDuoji; long getTime(){ digitalWrite(Trig,HIGH); delayMicroseconds(10);//10微妙 digitalWrite(Trig,LOW); return pulseIn(Echo,HIGH); } void initSuperVoice(){ pinMode(Echo,INPUT); pinMode(Trig,OUTPUT); } void setup() { initSuperVoice(); myDuoji.attach(DuoPIN); pinMode(BEEF,OUTPUT);//设置 digitalWrite(BEEF,HIGH); Serial.begin(115200); } void loop() { //获取距离 long distant; distant = getTime() / 58; if(distant <= 15){ Serial.print(distant); Serial.print("cm"); Serial.println(); digitalWrite(BEEF,LOW);//蜂鸣器发声 delay(500); digitalWrite(BEEF,HIGH);//蜂鸣器关闭 Serial.println("open!"); myDuoji.write(90); delay(2000); }else{c digitalWrite(BEEF,HIGH); Serial.println("close!"); myDuoji.write(180); } }
1、Serial.begin(115200);//开启端口
2、Serial.println();//输出
3、Serial.available();
#include <Servo.h> #define Echo D2 #define BEEF D3 #define Trig D8 #define DuoPIN D5 Servo myDuoji; long getTime(){ //超声波的测距 digitalWrite(Trig,HIGH); delayMicroseconds(10);//10微妙 digitalWrite(Trig,LOW); return pulseIn(Echo,HIGH); } void initSuperVoice(){ //初始化超声波模块接口 pinMode(Echo,INPUT); pinMode(Trig,OUTPUT); } void setup() { initSuperVoice(); myDuoji.attach(DuoPIN); pinMode(BEEF,OUTPUT);//设置 digitalWrite(BEEF,HIGH); Serial.begin(115200); } void loop() { //获取距离 long distant; distant = getTime() / 58; if(distant <= 15){ Serial.print(distant); Serial.print("cm"); Serial.println(); digitalWrite(BEEF,LOW); delay(500); digitalWrite(BEEF,HIGH); Serial.println("open!"); myDuoji.write(90); delay(1500); }else{ digitalWrite(BEEF,HIGH); //Serial.println("close!"); myDuoji.write(180); } }
1、串口调试小助手的手动发送要调成16进制
命令行模式:(默认此模式)从输入模式回到命令行模式:ESC;ESC按完,insert消失。
输入模式:按 i 进入,看到insert就能编辑代码。
按:(冒号) + wq。
w:保存
q:退出
gcc a.c -o X // (a.c是你要编译的c文件名字,X是生成的程序名)
./程序名,eg:./a
(命令模式下)要复制的行数+yy 复制代码
(命令模式下)行数 + dd 删除
(命令模式下)U 回到上一步
删除或者拷贝内容后,直接输入“p”,即可粘贴
dw 表示删除从当前光标到光标所在单词结尾的内容.
d0 表示删除从当前光标到光标所在行首的内容.
d$ 表示删除从当前光标到光标所在行尾的内容.
dd 表示删除光标所在行.
6dd 表示删除6行
D 表示删除从当前光标到光标所在行尾的内容.
:6,10 delete 表示删除第6行至第10行的数据,其中“delete”可以简写为“d”或“del”等等。---删除大量行时使用
yw 表示拷贝从当前光标到光标所在单词结尾的内容.
y0 表示拷贝从当前光标到光标所在行首的内容.
y$ 表示拷贝从当前光标到光标所在行尾的内容.
yfa 表示拷贝从当前光标到光标后面的第一个a字符之间的内容.
yy 表示拷贝光标所在行.
8yy 标识拷贝8行
:6,10 copy 18
表示从第6行开始的5行(即从第6行到第10行)数据复制到了第18行下面,其中“copy”也可写为“co”或“cop”。---拷贝大量行时使用
命令 | 功能 |
---|---|
ctrl + alt+ T | 打开命令行终端 |
xrandr | 显示可调的分辨率 |
xrandr -s + 分辨率 | 调整分辨率 |
ctrl + L | 清屏 |
ls | 列出当前文件夹下有哪些文件 |
ls - a | 显示所有文件,包括隐藏文件 |
vi 文件名.c + 回车 | 创建C类型的文件 |
pwd | 显示当前所在路径 |
mkdir + 文件名 | 新建一个文件夹(同Windows系统) |
cd + 回车 | 直接回到工作路径:/home/User |
cd + 文件夹名称 | 进入某个文件夹 |
cd … | 回退到上一级 |
TAB键 | 补全文件名 |
man 函数名 | 显示函数名的用法 |
man 2 函数名 | 显示函数名的用法 |
mv *.c MyDocument | 把.c类型的文件移动到MyDocument文件夹下; |
mv a.c b.c | 将a.c命名位b.c |
cp b.c test.c | 把b.c 拷贝成test.c |
cp a.out /mnt/hgfs/CodeFromWindows/ | 把a.out传到Win系统中 |
ifconfig | IP地址(Linux) |
ipconfig | IP地址(Windows) |
ls -l | 列举文件的清单 |
mv calculatorT.c ~ | 将该文件移动到工作目录 |
cp ~/calculatorT.c . | 将该文件从工作目录移动到当前路径 |
file 编译文件名 | 查看编译文件的运行环境,如ARM、X86-64等… |
scp 文件名 pi@192.168.43.30:home/pi | 将文件远程拷贝到其他主机,开发板用户名@开发板地址:开发板的绝对路径。 |
kill -9 进程的PID | 杀死该进程 |
grep gcc * -nir | grep gcc 在所有的文件当中去匹配gcc字段,*代表所有的文件,-nir:n显示行号,i不区分大小写,r是递归,一个目录一个目录找进去 |
rm -r wiringpi/ | 删除多文件夹目录的时候就要用到-r |
history | 显示当前终端窗口用过的命令, |
history |grep 匹配符 | 显示所有敲过的带“匹配符”的历史命令 |
sudo apt-get install build-essential | 安装gcc编辑器 |
sudo apt-get install net-tools | 安装ifconfig |
uname -r | 查看内核版本 |
while 指令 | whitch ls,查看ls指令所在目录 |
du 文件名 | 计算文件大小(Kb) |
gg=G | 整理代码格式 |
find -name 文件名 | 查找文件 |
cd /mnt/hgfs/共享文件夹名称/
注意:一般不要在该路径下直接操作,会出现权限问题
解决办法:cp cd /mnt/hgfs/共享文件夹名称/FirstLinuxCode.c .
将.c文件拷贝到工作路径(/home/CLC)
**Host:**localhost
**Port:**14147
**Password:**123
ls -l | 列举当前路径的文件清单,及属性 |
---|---|
- rwxr - xr - x | 横杠“-”:代表普通文件,r:read,w:write,x:可执行文件 |
rm 文件名 | 删除文件 |
#include <sys/types.h>//头文件
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
fd = open("./file1",O_RDWR); //打开这个文件,可以读和写入
fd = open("./file1",O_RDWR | O_CREAT,0600); //打开这个文件,如果没有的话就创建,
/*
0600给文件的所有者相应的权限
1.可读 r 4
2.可写 w 2
3.执行 x 1
0600代表:4 + 2
*/
char *buf = {"DuShangkun hen shuai!!!"}; // 要写入的字符串
fd = open("./file1",O_RDWR); //打开一个文件
write(fd,buf,strlen(buf)); //写入操作,strlen(buf)为字符串的长度,不能用sizeof();
close(fd);
char *buf = {"DuShangkun hen shuai!!!"}; // 要写入的字符串
fd = open("./file1",O_RDWR); //打开一个文件
int n_write = write(fd,buf,strlen(buf)); //n_write是写入的字节数
/*___________________*/
char *readBuf; //读取出来的字符存到该字符串里面
readBuf = (char *)malloc(sizeof(char)*n_write);//申请空间,防止野指针的出现
int n_read = read(fd,readBuf,n_write);
/*
这么写是对的,但是无法读取结果,原因就是光标在文件的尾巴,而read()只能读光标后面的字符。
解决方法:
1. 写入字符后,关闭fd,再重新打开。close(fd);在第四行输入该函数。
2. 不关闭fd,将光标移到最前面。见下一节
*/
printf("%s\n",readBuf);
close(fd);
SEEK_SET(); //宏定义:字符头位置
SEEK_END(); //字符尾巴位置
SEEK_CUR(); //当前位置
char *buf = {"DuShangkun hen shuai!!!"}; // 要写入的字符串 fd = open("./file1",O_RDWR); //打开一个文件 int n_write = write(fd,buf,strlen(buf)); //n_write是写入的字节数 char *readBuf; //读取出来的字符存到该字符串里面 readBuf = (char *)malloc(sizeof(char)*n_write);//申请空间,防止野指针的出现 lseek(fd,0,SEET_SET); //光标跳到距离头 0 个位置的地方 <=> 移到头, /* lseek(fd,2,SEET_SET); //第二个参数>0表示在最前面的位置再向右移动2个位置 lseek(fd,-2,SEET_SET); //<0表示向左移动,如果超边界,就移动到最边上 lseek(fd,-32,SEET_END); 返回值是光标移动的次数,所以,当打开一个文件,再将光标跳转到尾巴,可以计算出文件的大小。 */ int n_read = read(fd,readBuf,n_write); printf("%s\n",readBuf); close(fd);
函数原型
int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); int creat(const char *pathname, mode_t mode); //Flags:这三个只能指定一个 O_RDONLY //只读打开 O_WRONLY //只写打开 O_RDWR //可读可写打开 //-----------可通过 或'|' 的方式 添加以下功能------------------ O_CREAT O_EXCL O_APPEND //每次写入时,都添加到文件的尾端,不会覆盖之前的内容 fd = open("./file1",O_RDWR | O_APPEND); fd = open("./file1",O_RDWR);//会覆盖原来字节的位置,而不是把已有的全部删掉, //注意!!换行'\n'也算一个字符 O_TRUNC //将内容全部清零
eg:touch file1
int creat(const char *pathname, mode_t mode);
宏表示 | 数字 | 功能 |
---|---|---|
S_IRUSR | 4 | 可读 |
S_IWUSR | 2 | 可写 |
S_IXUSR | 1 | 可执行 |
S_IRWXU | 7 | 可读、写、执行 |
int fd;
fd = creat("/home/CLC/file1",S_IRWXU);
5.2.6 文件描述符
宏定义了,0,1,2;
0:标准输入;
1:标准输出;
2:错误
ps | 显示所有进程 |
---|---|
ps -aux | |
ps -aux|grep init | |
top | |
ipcs -m | 查看系统有哪些共享内存 |
ipcrm -m 共享内存ID | 删除某个共享内存 |
fork创建一个子进程的一 般目的
(1)一个父进程希望复制自己,使父、子进程同时执行不同的代码段。这在网络服务进程
中是常见的一父 进程等待客户端的服务请求。当这种请求到达时,父进程调用fork,使子
进程处理此请求。父进程则继续等待下-个服务请求到达。
(2) -一个进程要执行一个不同的程序。这对shelI是常见的情况。在这种情况下,子进程从
fork返回后立即调用exec (我们将在8.10节说明exec)。
vfork函数也可以创建进程,与fork有什么区别
关键区别一:
vfork直接使用父进程存储空间,不拷贝。
关键区别二:
vfork保证子进程先运行,当子进程调用exit退出后,父进程才
执行。
1… Main函数调用return
2.进程调用exit(),标准c库
3.进程调用_______exit(或者_______Exit(),. 属于系统调用
补充:
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> int main(){ pid_t pid; int cnt = 0; int status = 10; pid = fork(); if(pid > 0){ wait(&status);/* wait();当子进程没有全部结束时,主进程会一直堵塞在这里,直到子进程结束,返回一个exit()值给status */ printf("child qiut ,status = %d\n",WEXITSTATUS(status));//宏转换,传给Exit函数 while(1){ printf("this is father print,pid = %d\n",getpid()); sleep(3); printf("cnt = %d\n",cnt); } } else if(pid == 0){ while(1){ printf("this is child print.pid = %d\n",getpid()); sleep(3); cnt++; if(cnt == 3){ exit(4); } } } return 0; }
5.4.2 无名管道 FIFO
一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等
这些服务完全可以通过1个IP地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP地址与网络服务的关系是一对多的关系。
实际上是通过“IP地址+端口号"来区分不同的服务的。端口提供了一种访问通道,
服务器一般都是通过知名端口号来识别的。例如,对于每个TCP/IP实现来说,FTP服务器的TCP端口号都是21,每个Telnet服务器的TCP端口号都是23,每个TFTP(简单 文件传送协议)服务器的UDP端口号都是69。
Little endian小端字节序:将低序字节存储在起始地址
Big endian 大端字节序:将高序字节存储在起始地址
网络字节序=大端字节序
int socket(int domain, int type, int protocol);
指明所使用的协议族,通常为AF_INET ,表示互联网协议族( TCP/IP协议族) ;
●AF_ INET IPv4因特网域
●AF_INET6 IPv6因特网域
AF_UNIX Unix域
●AF_ROUTE 路由套接字
●AF_KEY密钥套接字
AF_UNSPEC 未指定
●SOCK STREAM:
流式套接字提供可靠的、面向连接的通信流;它使用TCP协议,从而保证了数据传输的正确性和顺序性
●SOCK DGRAM
数据报套接字定义了一种无连接的服,数据通过相互独立的报文进行传输,是无序的,并且不保证是可靠、无差错的。它使用数据报协议 UDP。
●SOCK RAW
允许程序使用低层协议,原始套接字允许对底层协议如IP或ICMP进行直接访问,功能强大但使用较为不便,主要用于一些协议的开发。
通常赋值"0”。
●日选择type类型对应的默认协议
●IPPROTO TCP TCP传输协议
●IPPROTO _UOP UDP传输协议
●IPPROTO SCTP SCTP传输协议
●IPPROTO TIPC TIPC传输协议*
#include <sy/types.h> / See NOTES”/ #include <sys/socket.h> int bind(int sockfd, const struct sockaddr *addr, socklen_ t addrlen);
- 1
- 2
- 3
- 4
功能
用于绑定IP地址和端口号到socketfd
参数
sockfd
是一个socket描述符
addr
是一 个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针,指向要绑定给sockfd的协议地址结构,这个地址结构根据地址创建socket时的地址协议族的不同而不同
//ipv4对应的是:
struct sockaddr{
unisgned short as_ _family; //协议族
char sa_ data[14]; //IP+端口
};
//同等替换:
struct sockaddr_in {
sa_family_t sin_ famQJy; /* 协议族1/
in_port_t sin_ port; /* 端口号"/
struct in_addr sin_ addr; /IP地址结构体*/
unsigned char sin_ _zero[8]; /* 填充没有实际意义只是为跟sockaddr结构在内存中对齐这样两者才能相互转换*/
int inet_ aton(const char* straddr,struct in_ addr *addrp);/*把字符串形式的"192.168.1.123"转为网络能识别的格式*/
char* inet_ ntoa(struct in_ addr inaddr);/*把网络格式的ip地址转为字符串形式*/
#include <sys/types.h>/ See NOTES /
#include <sys/socket.h>
int listen(int sockfd, int backlog);
设置能处理的最大连接数,listen**()** 并未开始接受连线,只是设置sockect的listen模式,listen 函数只用于服务器端,服务器进程不知道要与谁连接,因此,它不会主动地要求与某个进程连接,只是一直监听是否有其他客户进程与之连接, 然后响应该连接请求,并对它做出处理,一个服务进程可以同时处理多个客户进程的连接。主要就两个功能:将一个未连接的套接字转换为一个被动套接字(监听),规定内核为相应套接字排队的最大连接数。
内核为任何-个给定监听套接字维护两个队列:
未完成连接队列,每个这样的SYU 报文段对应其中项:已由某个客户端发出并到达服务器,而服务器正在等待完成相应的TCP三次握手
过程。这些套接字处于SYN_REVD状态:
已完成连接队列,每个已完成TCP三次握手过程的客户端对应其中-项。 这些套接字处于ESTABLISHED状态
#include <sys/types.h> /* See NOTES */
#include' <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_ t *addrlen);
●accept 函数由TCP 服务器调用,用于从已完成连接队列队头返回下一个已完成连接。如果已完成连接队列为空,那么进程被投入睡眠。
●sockfd
sockfd是socket系统调用返回的服务器端socket描述符
●addr
用来返回已连接的对端(客户端)的协议地址
●addrled
客户端地址长度
● 该函数的返回值是一 个新的套接字描述符,返回值是表示已连接的套接字描述符,而第一 个参数是服务器监听套接字描述符。一个服务器通常仅
仅创建一个监听套接字, 它在该服务器的生命周期内一直存在。内核为每个由服务器进程接受的客户连接创建一个已连接套接字(表示 TCP三次握
手已完成,当服务器完成对某个给定客户的服务时,相应的已连接套接字就会被关闭。
/*在套接字通信中进行字节读取函数: read() , write()。与I/O中的读取函数略有区别,因为它们输入或输出的字节数比可能比请求的少。*/
1 ssize_t write(int fd, const void *buf,size_t nbytes);
2 ssize_t reld(int fd,void *buf,size_t nbyte);
3
4 /*说明
5 *函数均返回读或写的字节个数, 出错则返回-1
6 1*/
第一个将/* buf */中的/* nbytes */个字节写入到文件描述符/* fd */中,成功时返回写的字节数。第二个为从/* fd */中读取/* nbyte */个字节到/* buf */中,返回实际所读的字节数。详细应用说明参考使用/* read write */读写 socket (套节字)。
网络/* I/0 */还有一些函数例如: /*recv()/ send(),readv()/ writev(),recvmsg()/ sendmsg(),ecvfrom()/ sendto ()*/等
1 ssize. _t send(int s,const void *msg,size_ t len,int flags);
2 //包含3要素: 套接字s,待发数据msg,数据长度len
3 //函数只能对处于连接状态的套接字使用, 参数s为已建立好连接的套接字描述
4 //符, 即accept函数的返回值
5 //参数msg指向存放待发送数据的缓冲区
6 //参数len为待发送数据的长度, 参数flags为控制选项, -般设置为0
1 ssize. _t recv(int s,void *buf,size. _t len,int flags);
2 //包含3要素:套接字s,接收缓冲区buf,长度len
3 //函数recv%(参数s所指定的套接字描述符 (必须是面向连接的套接字)上接收
4 //数据并保存到参数buf所指定的缓冲区
5 //参数len则为缓冲区长度, 参数flags为控制选项, - 般设置为0
connect()函数:客户机连接主机
1 #include <sy/types.h> /* See NOTES */
2 #include <sys/socket.h>
3 int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
●该函数用于绑定之后的client端(客户端),与服务器建立连接
●sockfd
是目的服务器的sockect描述符
●addr
是服务器端的IP地址和端口号的地址结构指针
●addrlen
地址长度常被设置为sizeof(struct sockaddr)
●成功返回0,遇到错误时返回-1,并且errno中包含相应的错误码
#include <netinet/in.h>
uint16 t htons(uint16 t host16bitvalue); //返回网络字节序的值
uint32 t htonl(uint32 t host32bitvalue);
//返回网络字节序的值
uint16 t ntohs(uint16 t net16bitvalue); //返回主机字节序的值uint32_ t
ntohl(uint32 t net32bitvalue); //返回主机字节序的值
h代表host, n代表net, s代表short (两个字节),代表long (4个字节),通过上面的4个函数
可以实现主机字节序和网络字节序之间的转换。有时可以用INADDR ANY, INADDR ANY指定
地址让操作系统自己获取
覆盖SD卡根目录的’config.txt’文件。
# For more options and information see # http://rpf.io/configtxt # Some settings may impact device functionality. See link above for details # uncomment if you get no picture on HDMI for a default "safe" mode #hdmi_safe=1 # uncomment this if your display has a black border of unused pixels visible # and your display can output without overscan #disable_overscan=1 # uncomment the following to adjust overscan. Use positive numbers if console # goes off screen, and negative if there is too much border #overscan_left=16 #overscan_right=16 #overscan_top=16 #overscan_bottom=16 # uncomment to force a console size. By default it will be display's size minus # overscan. #framebuffer_width=1280 #framebuffer_height=720 # uncomment if hdmi display is not detected and composite is being output #hdmi_force_hotplug=1 # uncomment to force a specific HDMI mode (this will force VGA) #hdmi_group=1 #hdmi_mode=1 # uncomment to force a HDMI mode rather than DVI. This can make audio work in # DMT (computer monitor) modes #hdmi_drive=2 # uncomment to increase signal to HDMI, if you have interference, blanking, or # no display #config_hdmi_boost=4 # uncomment for composite PAL #sdtv_mode=2 #uncomment to overclock the arm. 700 MHz is the default. #arm_freq=800 # Uncomment some or all of these to enable the optional hardware interfaces #dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on # Uncomment this to enable infrared communication. #dtoverlay=gpio-ir,gpio_pin=17 #dtoverlay=gpio-ir-tx,gpio_pin=18 # Additional overlays and parameters are documented /boot/overlays/README # Enable audio (loads snd_bcm2835) dtparam=audio=on [pi4] # Enable DRM VC4 V3D driver on top of the dispmanx display stack dtoverlay=vc4-fkms-v3d max_framebuffers=2 [all] #dtoverlay=vc4-fkms-v3d dtoverlay=pi3-disable-bt //停止蓝牙,解除对串口的使用 start_x=1 gpu_mem=128
然后再修改根目录的“cmdline.txt”,将里面的内容全部替换成以下内容,以防万一,先备份
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
#console=serial0,115200 console=tty1 root=PARTUUID=ea7d04d6-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles
如果树莓派启动遇到以下问题…刷机吧…
end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,XX)
sudo passwd pi #修改默认的用户名为pi的密码,按照提示重复输入两次新密码即可
sudo passwd root #修改root账户的初始密码
su root #切换登陆到root账户
su pi #切换到pi账户
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
nano 是文档编辑器
network={
ssid="SMXY-WIFI" /*注意:树莓派3B,WiFi的频率要设置成2.4GHZ,不要切换成5G的,不然检测不到*/
#psk=“密码”
key_mgmt=WPA-PSK
#NONE
}
指令:sudo nano /etc/rc.local
IP=$(hostname-I)||true
if["$IP"];then
printf "My IP address is 8s\n" "$ IP"
fi
ifconfig wlan0 192.168.43.123 //添加该行代码
exit 0
sudo raspi-config
sudo nano /etc/apt/sources.list
deb http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ stretch main contrib non-free rpi
#deb-src http://mirrors.tuna.tsinghuac.edu.cn/raspbian/raspbian/ stretch main contrib non-free rpi
sudo apt-get update //更新源
sudo apt-get install vim
Xrdp
sudo apt-get install xrdp
主机:sftp://192.168.1.115
用户名:pi
密码:1
静态库
是在程序执行前就加入到目标程序中去了
优点:
缺点:
动态库
是在程序执行时临时由目标去调用。
优点:
缺点:
运行慢
发布程序需要提供依赖的动态库
动态函数库同共享函数库是一个东西(在linux上叫共享对象库, 文件后缀是.so ,windows上叫动态加载函数库,文件后缀是.dll)
Linux中命名系统中共享库的规则
int add(int a,int b){
return a + b;
}
int sub(int a,int b){
return a - b;
}
int mul(int a,int b){
return a * b;
}
float div(int a,int b){
return (float)a / b;
}
int add(int a,int b);
int sub(int a,int b);
int mul(int a,int b);
float div(int a,int b);
#include <stdio.h> #include "calcufuncs.h" /*优先搜索并导入当前目录存在的头文件*/ int main(){ int a,b; while(1){ printf("Please input first value\n"); scanf("%d",&a); printf("Please input second value\n"); scanf("%d",&b); printf("%d + %d = %d\n",a,b,add(a,b)); printf("%d - %d = %d\n",a,b,sub(a,b)); printf("%d * %d = %d\n",a,b,mul(a,b)); printf("%d / %d = %g\n",a,b,div(a,b)); } return 0; }
mv calculatorT.c ~ | 将该文件移动到工作目录 |
---|---|
cp ~/calculatorT.c . | 将该文件从工作目录移动到当前路径 |
以以上三个文件为例:
calcufuncs.c
calcufuncs.h
calcumain.c
静态库文件名的命名方式是 libxxx.a
,库名前加lib
,后缀用.a
,xxx
为静态库名。
1. 先生成.o文件
gcc calcufuncs.c -c
2. 再将.o文件打包
#ar rcs 静态库的名字.a 原材料.o(.o文件)
ar rcs libcalcufunc.a calcufuncs.o
ar指令不会用:ar加Enter键可获取所有用法
1. 目录下已有这些文件
calcufuncs.c calcufuncs.h calcumain.c libcalcu.a
2. 对主函数进行编译
gcc calcumain.c -lcalcu #-l + 库名(砍头去尾)
发现系统会报错
解决办法:指定库的所在路径
gcc calcumain.c -lcalcu -L ./ -o mainProStatic
意思是:在当前文件去链接calcu静态库
# -L告诉gcc编辑器从-L指定的路径去找静态库。默认从/usr/lib 或 /usr/local/lib找
# -o mainProStatic给编译文件起个名字
动态库的命名方式与静态库类似,前缀相同,为lib
,后缀变为.so
,所以为libmytime.so
。
原材料:源代码.c 或者 .cpp
直接打包
gcc -shared -fpic calcufuncs.c -c -o libcalcu.so
-shared 指定生成动态库
-fpic 标准,fpic选项作用于编译阶段,在生成目标文件时就得使用该选项,以生成位置无关的代码
#### (3)动态库的使用
```powershell
gcc calcumain.c -lcalcu
也会出现上面的情况:找不到
应该:
gcc calcumain.c -lcalcu -L ./ -o mainProDyno
运行:
./mainProDyno
结果:发现找不到这个库
因为动态库是在程序执行时(临时)由目标去调用
解决方法:
/*将动态库拷贝到默认路径下*/
sudo cp libcalcu.so /usr/lib
/*再运行*/
完美解决!!!
#export LD_LIBRARY_PATH="动态库的路径名" 在终端命令输入: export LD_LIBRARY_PATH="/home/pi/myCode/LinuxStockFile/test" 但该路径只是临时的,换一个窗口就不能用了(只要窗口不变就有效) 可以写个脚本快速执行搭建路径的指令 vi start.sh 输入以下东西 export LD_LIBRARY_PATH="/home/pi/myCode/LinuxStockFile/test" ./mainProDyno 然后 :wq #给脚本添加权限 chmod +x start.sh #运行 ./start.sh
gpio readall //树莓派的所有io口
/*驱动一个继电器*/ #include <wiringPi.h> #include <stdio.h> #include <stdlib.h> #define Relay 7 int main(){ int cmd; if(wiringPiSetup() == -1) { printf("IO init failure!\n"); return -1; } pinMode(Relay,OUTPUT); //定义接口类型 while(1){ printf("please input 0 or 1: 0 - OFF , 1 - ON\n"); scanf("%d",&cmd); //输入指令 if(cmd == 0) digitalWrite(Relay,HIGH); printf("you turn OFF the Relay!\n"); } else if(cmd == 1) { digitalWrite(Relay,LOW); printf("you turn ON the Relay!\n"); } else { printf("input error!\nplease check your input value(just 0 or 1)\n"); } } return 0; }
/*控制多个继电器*/ #include <wiringPi.h> #include <stdio.h> #include <stdlib.h> #define Relay1 21 #define Relay2 22 #define Relay3 23 #define Relay4 24 void initRelay() { pinMode(Relay1,OUTPUT); pinMode(Relay2,OUTPUT); pinMode(Relay3,OUTPUT); pinMode(Relay4,OUTPUT); digitalWrite(Relay1,HIGH); digitalWrite(Relay2,HIGH); digitalWrite(Relay3,HIGH); digitalWrite(Relay4,HIGH); } void controlRelay(int cmd) { switch(cmd) { case 1: digitalWrite(Relay1,LOW); printf("you turn ON the Relay1!\n"); break; case 2: digitalWrite(Relay2,LOW); printf("you turn ON the Relay2!\n"); break; case 3: digitalWrite(Relay3,LOW); printf("you turn ON the Relay3!\n"); break; case 4: digitalWrite(Relay4,LOW); printf("you turn ON the Relay4!\n"); break; case 100: digitalWrite(Relay1,LOW); digitalWrite(Relay2,LOW); digitalWrite(Relay3,LOW); digitalWrite(Relay4,LOW); printf("you turn ON all Relay!\n"); break; case -1: digitalWrite(Relay1,HIGH); printf("you turn OFF the Relay1!\n"); break; case -2: digitalWrite(Relay2,HIGH); printf("you turn OFF the Relay2!\n"); break; case -3: digitalWrite(Relay3,HIGH); printf("you turn OFF the Relay3!\n"); break; case -4: digitalWrite(Relay4,HIGH); printf("you turn OFF the Relay4!\n"); break; case -100: digitalWrite(Relay1,HIGH); digitalWrite(Relay1,HIGH); digitalWrite(Relay2,HIGH); digitalWrite(Relay3,HIGH); digitalWrite(Relay4,HIGH); printf("you turn OFF all Relay!\n"); break; default: printf("input error!\nplease check your input\n"); break; } } int main(){ int cmd; if(wiringPiSetup() == -1) { printf("IO init failure!\n"); return -1; } initRelay(); while(1) { printf("-----------------------\nplease input a int...\n"); scanf("%d",&cmd); controlRelay(cmd); } return 0; }
#include <wiringPi.h> #include <stdio.h> #include <sys/time.h> #define Trig 4 #define Echo 5 void superIo_Init() { pinMode(Trig,OUTPUT); pinMode(Echo,INPUT); } float disMeasure() { struct timeval t1; struct timeval t2; long t_launch,t_receive; float dis; digitalWrite(Trig,LOW); delayMicroseconds(2); digitalWrite(Trig,HIGH); //发出超声波脉冲 delayMicroseconds(10); digitalWrite(Trig,LOW); while(digitalRead(Echo) != 1); gettimeofday(&t1,NULL); //获取当前时间 开始接收到返回信号的时候 while(digitalRead(Echo) != 0); gettimeofday(&t2,NULL);//获取当前时间 最后接收到返回信号的时候 t_launch = t1.tv_sec * 1000000 + t1.tv_usec; //微秒级的时间 t_receive = t2.tv_sec * 1000000 + t2.tv_usec; //微秒级的时间 dis = (float)(t_receive - t_launch)/1000000 * 34000 / 2; return dis; } int main(){ float dis; if(wiringPiSetup() == -1) { printf("setup wiringPi failed!\n"); return -1; } superIo_Init(); while(1) { dis = disMeasure(); printf("distance = %gcm\n",dis); delay(1000); } return 0; }
#include <wiringPi.h> #include <sys/time.h> #include <stdio.h> #include <stdlib.h> #define Relay 21 #define Trig 4 #define Echo 5 void superIo_Init() { pinMode(Trig,OUTPUT); pinMode(Echo,INPUT); } float disMeasure(void) { struct timeval t1; struct timeval t2; long t_launch,t_receive; long t_launch,t_receive; float dis; digitalWrite(Trig,LOW); delayMicroseconds(2); digitalWrite(Trig,HIGH); delayMicroseconds(10); digitalWrite(Trig,LOW); while(digitalRead(Echo) != 1); gettimeofday(&t1,NULL); while(digitalRead(Echo) != 0); gettimeofday(&t2,NULL); t_launch = t1.tv_sec * 1000000 + t1.tv_usec; t_receive = t2.tv_sec * 1000000 + t2.tv_usec; dis = (float)(t_receive - t_launch) / 1000000 * 34000 / 2; return dis; } int main(){ int cmd; float dis = 0.0; if(wiringPiSetup() == -1) { printf("IO init failure!\n"); return -1; } pinMode(Relay,OUTPUT); digitalWrite(Relay,HIGH); superIo_Init(); while(1){ dis = disMeasure(); printf("dis = %g cm\n",dis); if(dis < 15.0) { digitalWrite(Relay,LOW); printf("dis = %g cm,Relay Open!!\n",dis); } else { digitalWrite(Relay,HIGH); printf("dis = %g cm,Relay Close!!\n",dis); } delay(1000); } return 0; }
#include <wiringSerial.h> #include <wiringPi.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> int main(){ int fd; int nread; char cmd[128] = {'\0'}; wiringPiSetup(); fd = serialOpen("/dev/ttyAMA0",9600); while(1){ nread = read(fd,cmd,sizeof(cmd)); while(strlen(cmd) == 8){ if(strstr(cmd,"ON")){ printf("open light\r\n"); } if(strstr(cmd,"OFF")){ printf("close light\r\n"); } memset(cmd,'\0',sizeof(cmd)); } } return 0; }
两个人同时互骂;
同一时间只能一个骂,一个听。
是什么=?
交叉编译是在一个平台上生成另一个平台上的可执行代码。我们再windows上面编写C51代码,并编译成可执行代码,如XX . hex, 是在C51上面运行,不是在windows, 上面运行
我们在ubuntu上面编写树莓派的代码,并编译成可执行代码,如a. out,是在树莓派上面运行,不是在ubuntu linux 上面运行
编译:是在一个平台上生成在该平台上的可执行代码
C51交叉编译的发生在keil(集成环境上面)
STM32
=为什么要交叉编译=:
平台上不允许或不能够安装我们所需要的编译器比如C51
因为目的平台上的资源贫乏,无法运行我们]所需要编译器
*树莓派是不是就不需要交叉编译====*?
错。也要.树莓派有时又是因为目的平台 还没有建立,连操作系统都没有,根本谈不上运行什么编译器。
操作系统也是代码,也要编译!
平台运行需要两样至少东西: bootloader (启动引导代码)以及操作系统核心
宿主机(host) : 编辑和编译程序的平台,-般是基于X86的PC机,通常也被称为主机。
目标机(target) : 用户开发的系统,通常都是非X86平台。host编译得到的可执行代码在target上运行。
交叉编译需要用到工具:
交叉编译器
压缩包地址: https://github.com/raspberrypi/
解压
unzip tools-masters.zip
cd ~/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
pwd获得路径
echo $PATH //获取当前变量的值
PATH 环境变量
CLC@Embed_Learn:~/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin$ export PATH = /usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/CLC/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bicn
修改工作目录下的.bashrc隐藏文件,配置命合终端的
vi /home/CLC/ .bashrc
在文件最后一行加入:
export PATH = /usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/CLC/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
source home/CLC .bashrc # 生效配置
arm-linux-gnueabihf-gcc -v # 查看版本号
显示:
gcc version 4.8.3 20140303 ........
arm-linux-gnueabihf-gcc xxx.c -o xxx # 编译文件
scp test_2 pi@192.168.43.30:home/pi/ # 将编译文件拷贝到开发板上
正常我们先要交叉编译wiringPi库,编译出的库适合树莓派,这时候交叉编译可执行程序的时候,链接库的格式也是正确的。
通过-I -L来指定
因为链接的库的格式不对,是宿主机的平台,出现以下错误
arm-linux- gnueabihf-gcc demo2.c -I /home/CLC/lessonPI/WiringPi/wiringPi - lwiringPi/home/CLC/lessonPI/tools- master/ arm- bcm2708/ gcc-linaro- arm- 1linux”gnue abihf-raspbian-x64/bin/ ../1ib/gcc/
arm-linux- gnueabihf/4.8.3/../../../../arm-linux- gnueabihf/bin/1d: cannot find -1wiringPi collect2: error: 1d returned 1 exit status
解决办法
把树莓派的wiringpi库拿来用
1、
#下位机
cd /usr/lib
[外链图片转存失败,源站可能有防```盗链机制,!建wiriPi库]议将(D:\MyDocumetQAPVStudy Note\嵌入式开发\wiringPi库.png)D:\MyDocument\Study Note\嵌入式开发\wiringPi库.png)]
2、
# 下位机
ls -l |grep wiringPi
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qtsFAXxo-1616205631600)(D:\MyDocument\Study Note\嵌入式开发\wiringPi库2.png)]
有‘->’的说明是软链接
3、
# 下位机
scp libwiringPi.so.2.50 CLC@192.168.43.52:/home/CLC
ln -s libwiringPi.so.2.50 libwiringPi.so
指令 参数 要被链接的文件 定义的名字
参考链接: https://www.cnblogs.com/zhangna1998517/p/11347364.html.
概念:
软链接文件有类似于Windows的快捷方式。
在符号连接中,文件实际上是一个文本文件,其中包含的有另一文件的位置信息。
你选定的位置上生成一个文件的镜像,不会占用磁盘空间
如何生成:
ln -s libwiringPi.so.2.50 libwiringPi. so
指令 参数 要被链接的文件 软链接文件名字
硬链接: 它会在你选定的位置,上生成一个和源文件大小相同的文件
ln libwiringPi.so.2.50 libwiringPi.so
# 备份源列表
sudo cp /etc/apt/sources.list /etc/apt/sources.list_backup
# 打开sources.list文件
sudo nano /etc/apt/sources.list
# 编辑/etc/apt/sources.list文件, 在文件最前面添加阿里云镜像源:
# 阿里源
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
# 刷新列表
sudo apt-get update
#sudo apt-get upgrade
sudo apt-get install build-essential
链接: https://www.cnblogs.com/linjiaxin/p/6476480.html.
dsk@DSK:~/System/linux-rpi-4.19.y$ ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make -j4 zImage modules dtbs
dsk@DSK:~/System/linux-rpi-4.19.y$ cp arch/arm/boot/dts/.*dtb* /home/dsk/data1/
dsk@DSK:~/System/linux-rpi-4.19.y$ cp arch/arm/boot/dts/overlays/.*dtb* /home/dsk/data1/overlays/
dsk@DSK:~/System/linux-rpi-4.19.y$ cp arch/arm/boot/dts/overlays/README /home/dsk/data1/overlays/
#include <stdio.h> struct Animal{ char name[20]; int sex; int age; void (*peat)(); void (*pjump)(); }; void dogEat(){ printf("狗吃屎\n"); } void catEat(){ printf("猫吃鱼\n"); } void duckEat(){ printf("鸭子吃米\n"); } void dogjump(){ printf("狗跳\n"); } void catjump(){ printf("猫跳\n"); } void duckjump(){ printf("鸭子跳\n"); } int main(){ struct Animal dog = {"大黄",1,4,dogEat(),dogjump()}; struct Animal cat = { .age = 3, .peat = catEat(), .pjump = catjump() }; //struct Animal duck; dog.peat; cat.peat; return 0; }
#include "h_ControlDevices.h" struct Device* findDeviceByName(char *name,struct Device *phead){ struct Device *tmp = NULL; tmp = phead; if(tmp == NULL){ return NULL; }else{ while(tmp != NULL){ if(strcmp(tmp->dev_Name,name) == 0){ return tmp; } //tmp->dev_Init(); tmp = tmp->next; } return NULL; } } int main(int argc, char *argv[]) { int x; char name[32]; if(wiringPiSetup() == -1){ return -1; } struct Device *pDeviceHead = NULL; pDeviceHead = add_Bathroom_Light_To_Dev_Link(pDeviceHead); pDeviceHead = add_Second_Floor_Light_To_Dev_Link(pDeviceHead); pDeviceHead = add_Livingroom_Light_To_Dev_Link(pDeviceHead); pDeviceHead = add_Restaurant_Light_To_Dev_Link(pDeviceHead); pDeviceHead = add_Fire_Listen_To_Dev_Link(pDeviceHead); while(1){ memset(name,'\0',sizeof(name)); printf("====input name====\n"); scanf("%s",name); struct Device *tmp = findDeviceByName(name,pDeviceHead); if(tmp == NULL){ printf("This is NULL!\n"); }else{ tmp->dev_Init(); while(1){ printf("***input cmd***\n"); scanf("%d",&x); if(x == 0)break; tmp->dev_Change_Status(x); //printf("Device Name:%s\n",tmp->dev_Name); //printf("Device Pin_Num:%d\n",tmp->pin); } } } return 0; }
相对有刷电机,无刷电机的命名好理解很多,一般它由四个数字组成,例如2040无刷电机。这个数字仅代表电机的外形尺寸,2040表示直径为20mm,长度为40mm的电机。同理3650无刷电机表示此电机直径36mm,长度50mm。
其实370有刷电机的大小和2530无刷电机一样,540电机的大小和3650无刷电机一样。
外转子无刷电机
磁铁“包”在外面。而A、B、C电极在里边。
电机的扭力更大,但转速却上不来。
在模型中,一般外转子无刷电机的KV值在2000以内,而内转子无刷电机则可以到8000-9000kv。
一般飞机上常见外转子无刷电机,而模型车和模型船一般都使用内转子无刷电机。
刚才说了无刷电机的转速是靠交流电频率决定的,那么电调要想方设法弄明白目前电机的转速以及当前电机的状态。其实这对已经正常运转的电机来说很容易,但对于一个刚刚起步或者运行速度很慢的电机来说就显得比较麻烦了(很难较准确的测出电机转速的状态),所以无感无刷电机会在低速时线性不好甚至可能会颤抖,而起步的扭力也难以强过同等级有刷电机。
但是人们发现无论什么运行状态的无刷电机,它的霍尔效应都是明显的,所以通过霍尔效应电调可以很容易的知道无论高速还是低速电机的运行状态,从而解决了无感无刷电机的毛病!但就目前来看霍尔传感器并不是廉价货,所以有感无刷电机、电调的价格会比无感无刷贵上许多。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。