差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
a40i [2023/08/13 22:53]
hc
a40i [2023/08/23 20:09] (当前版本)
hc [Linux C编程指导]
行 8: 行 8:
 } }
 ====接口布局和尺寸==== ====接口布局和尺寸====
- 
- 
- 
- 
-====快速上手==== 
-===系统下载=== 
-==Linux系统== 
-Buildroot: 
- 
-===工具链下载=== 
-==工具== 
- 
-===烧录工具下载=== 
-==烧录工具== 
- 
-===系统烧录=== 
-1、下载烧录工具: 
-  *  
- 
-2、开始烧录: 
-  
- 
- 
-3、完成烧录: 
-  * 烧录过程不需要任何操作,烧录成功后右框会显示设备自动重启,烧录完成。 
  
  
行 126: 行 101:
          
  ===串口使用方法===  ===串口使用方法===
- ==串口定义== 
-{{:pasted:20220607-205252.png}} 
  ==RS485==  ==RS485==
  
行 143: 行 116:
  
   com_send /dev/ttyS3 115200   com_send /dev/ttyS3 115200
-  {{:pasted:20230813-225324.png}}+  
        
  ==RS232==  ==RS232==
行 159: 行 132:
 在接收端可以收到字符: 在接收端可以收到字符:
  
- {{:pasted:20230813-225050.png}}+{{:pasted:20230823-194608.png}} 
 + 
  
  ===CANBUS使用方法===  ===CANBUS使用方法===
-CAN接口定义 
  
-{{:pasted:20220607-232222.png}} 
- 
-CAN测试方法,连接CAN1L -- CAN2L ,CAN1H -- CAN2H 
 设置can: 设置can:
  
行 172: 行 142:
   ip link set can0 type can bitrate 125000   ip link set can0 type can bitrate 125000
   ip link set can0 up   ip link set can0 up
- 
- 
-  ip link set can1 down 
-  ip link set can1 type can bitrate 125000 
-  ip link set can1 up 
  
 使用can0 接收: 使用can0 接收:
  
   candump can0   candump can0
-使用can1发送数据帧+使用can分析仪发送数据帧
      
-  cansend can1 123#1122334455667788+ 
 查看接收端: 查看接收端:
  
行 190: 行 155:
 C编程指导参考:[[np-8132-v0a#CAN应用编程|CAN应用编程]] C编程指导参考:[[np-8132-v0a#CAN应用编程|CAN应用编程]]
  
- ===左右拨码开关使用方法=== + ===RUN/STOP开关使用方法=== 
- +分别对应2个GPIO197、GPIO198 
-  [root@rk3399:~]# evtest                                --------------> 输入命令evtest +拨到RUN查看状态:
-  No device specified, trying to scan all of /dev/input/event* +
-  Available devices: +
-  /dev/input/event0: ff420030.pwm +
-  /dev/input/event1: gpio-decoder +
-  /dev/input/event2: gpio-keys +
-  /dev/input/event3: rk29-keypad +
-  Select the device event number [0-3]: 2                 -------------> 选择gpio-keys +
-  Input driver version is 1.0.1 +
-  Input device ID: bus 0x19 vendor 0x1 product 0x1 version 0x100 +
-  Input device name: "gpio-keys" +
-  Supported events: +
-  Event type 0 (EV_SYN) +
-  Event type 1 (EV_KEY) +
-    Event code 105 (KEY_LEFT) +
-    Event code 106 (KEY_RIGHT) +
-  Properties: +
-  Testing ... (interrupt to exit)                                                                        +
-  Event: time 1654670127.676876, type 1 (EV_KEY), code 105 (KEY_LEFT), value 0 +
-  Event: time 1654670127.676876, -------------- SYN_REPORT ------------ +
-  Event: time 1654670127.693874, type 1 (EV_KEY), code 106 (KEY_RIGHT), value 1         -------------> 拨到右边打印1 +
-  Eventtime 1654670127.693874, -------------- SYN_REPORT ------------ +
-  Event: time 1654670128.597949, type 1 (EV_KEY), code 106 (KEY_RIGHT), value 0 +
-  Event: time 1654670128.597949, -------------- SYN_REPORT ------------ +
-  Event: time 1654670128.610192, type 1 (EV_KEY), code 105 (KEY_LEFT), value 1          -------------> 拨到左边时打印1 +
-  Event: time 1654670128.610192, -------------- SYN_REPORT ------------ +
- +
-C编程指导参考:[[np-8132-v0a#Switch应用编程|Switch应用编程]] +
- +
- ===WATCHDOG使用方法=== +
-设置看门狗timeout超时时间 +
- +
-  i2ctransfer -y -f 4 w3@0x15 0x00 0x02 0x01     (1分钟) +
-  +
-以此类比 0x01=1分钟  0x02=2分钟 0x03=3分钟  +
- +
-打开watchdog+
  
-  i2ctransfer -y -f 4 w3@0x15 0x00 0x03 0x01  +  cat /sys/class/gpio/gpio197/value 
 +  为1 
 +  cat /sys/class/gpio/gpio198/value 
 +  为0
      
-喂狗:+ 拨到STOP时查看状态:
  
-  i2ctransfer -y -f 4 w3@0x15 0x00 0x04 0x01+  cat /sys/class/gpio/gpio197/value 
 +  为0 
 +  cat /sys/class/gpio/gpio198/value 
 +  为1
    
- ===LED使用方法===+  
 + ===DODI使用方法===
  
-{{:pasted:20220608-001138.png}} +    C源代码参考/root/dido/dido.c 
- +     
-系统共有8个LED,pwr_led不可以控制其中7个LED均可控,系统下对应的设备接口为: + ===移位寄存器的使用方法=== 
- +     
-  [root@rk3399:~]# cd /sys/class/leds/ +    移位寄存器控制0-F(DI)、0-F(DO)共计32个LED 
-  [root@rk3399:/sys/class/leds]# ls +    C源代码参考/root/dido/shift.c 
-   mmc1:: sys_led  work_led1  work_led2  work_led3  work_led4  work_led5 work_led6 +    
-控制work_led1熄灭 +
- +
-  echo 0 >/sys/class/leds/work_led1/brightness +
- +
-控制work_led1点亮 +
-   +
-  echo 1 >/sys/class/leds/work_led1/brightness +
-   +
- 其他LED类似+
  ===RTC使用方法===  ===RTC使用方法===
    
行 274: 行 201:
    Wed Jun  8 17:02:30 CST 2022    Wed Jun  8 17:02:30 CST 2022
  
- ===TFCARD使用方法=== 
- 
-接入TFCARD,如果TFCARD有分区,系统会自动挂载到/mnt/sdcard 
- 
-  [root@rk3399:/]# df 
-  Filesystem     1K-blocks    Used Available Use% Mounted on 
-  /dev/root       14781436  480548  13675260   4% / 
-  devtmpfs         1962984         1962984   0% /dev 
-  tmpfs            1963920      28   1963892   1% /dev/shm 
-  tmpfs            1963920     176   1963744   1% /tmp 
-  tmpfs            1963920     304   1963616   1% /run 
-  /dev/mmcblk0p6   3462176 2768616    497976  85% /mnt/sdcard 
- 
    
- ===十段位编码开关使用方法=== + ===FUN编码开关使用方法=== 
- +  
-  [root@rk3399:~]# evtest                                             --------------> 输入命令evtest +   C代码参考  /root/FUN/fun.c
-  No device specified, trying to scan all of /dev/input/event* +
-  Available devices: +
-  /dev/input/event0: ff420030.pwm +
-  /dev/input/event1: gpio-decoder +
-  /dev/input/event2: gpio-keys +
-  /dev/input/event3: rk29-keypad +
-  Select the device event number [0-3]: 1                             -------------> 选择1 gpio-decoder +
-  Input driver version is 1.0.1 +
-  Input device ID: bus 0x19 vendor 0x0 product 0x0 version 0x0 +
-  Input device name: "gpio-decoder" +
-   Supported events: +
-     Event type 0 (EV_SYN) +
-     Event type 3 (EV_ABS) +
-     Event code 0 (ABS_X) +
-       Value      6 +
-       Min        0 +
-       Max       15 +
-  Properties: +
-  Testing ... (interrupt to exit) +
-  Event: time 1654670726.561933, type 3 (EV_ABS), code 0 (ABS_X), value 7        -------------> 旋转编码开关,打印上报对应的值。 +
-  Event: time 1654670726.561933, -------------- SYN_REPORT ------------ +
-  Event: time 1654670728.565864, type 3 (EV_ABS), code 0 (ABS_X), value 8 +
-  Event: time 1654670728.565864, -------------- SYN_REPORT ------------ +
-  Event: time 1654670729.567865, type 3 (EV_ABS), code 0 (ABS_X), value 9 +
-  Event: time 1654670729.567865, -------------- SYN_REPORT ------------ +
-  Event: time 1654670731.571873, type 3 (EV_ABS), code 0 (ABS_X), value 0 +
-  Event: time 1654670731.571873, -------------- SYN_REPORT ------------ +
-   +
-C编程指导参考:[[np-8132-v0a#Rotary应用编程|Rotary应用编程]]+
  
  ===扩展IO卡使用方法===  ===扩展IO卡使用方法===
-GPO1~GPO16 对应的GPIO编号依次为480~495 
  
-GPI1~GPI16  对应的GPIO编号依次为496~511 +   C代码参考 /root/pca9555/pca9555.c 
- +   
-系统支持Linux标准的sysfs gpio操作,以GPO1(480)为例: +
- +
-  [root@rk3399:/sys/class/gpio]# echo 480 >export                      -------------> 导出GPO1 +
-  [root@rk3399:/sys/class/gpio]# echo out >gpio480/direction           -------------> 设置为输出  +
-  [root@rk3399:/sys/class/gpio]# echo 0 >gpio480/value                 -------------> 设置为低电平输出 +
-  [root@rk3399:/sys/class/gpio]# echo 1 >gpio480/value                 -------------> 设置为高电平输出 +
- +
-C编程指导参考:[[np-8132-v0a#GPIO应用编程|GPIO应用编程]]+
  ===USB接口使用===  ===USB接口使用===
  系统支持U盘自动挂载:/media/usb0  系统支持U盘自动挂载:/media/usb0
    
  
-   [root@rk3399:/]# df + 
-   Filesystem     1K-blocks   Used Available Use% Mounted on +
-  /dev/root       14781436 480556  13675252   4% / +
-  devtmpfs         1962984      0   1962984   0% /dev +
-  tmpfs            1963920     28   1963892   1% /dev/shm +
-  tmpfs            1963920    184   1963736   1% /tmp +
-  tmpfs            1963920    288   1963632   1% /run +
-  /dev/sda1        1046512   2728   1043784   1% /media/usb0   +
-   +
- ===CODESYS 实时性支持=== +
-系统已支持Fully Preemptible Kernel(RT),实时性内核版本为:+
  
-  [root@rk3399:/]# uname -r 
-   4.4.167-rt176 
-如下图为实时系统连接8台伺服间隔1ms运行效果: 
- 
-{{:pasted:20220610-004130.png}} 
- 
-CPU core分布: 
- 
-  cpu0:linux system  
-  cpu1:none 
-  cpu2:none 
-  cpu3:task 
-  cpu4: eth0  
-  cpu5: codecsys run time task 
-   
- {{:pasted:20220608-191107.png}} 
----- 
  ====Linux C编程指导====  ====Linux C编程指导====
 === 交叉编译环境 === === 交叉编译环境 ===
行 372: 行 221:
    Ubuntu 18.04 x86_64       Ubuntu 18.04 x86_64   
 2. 下载安装交叉编译工具链: 2. 下载安装交叉编译工具链:
-   apt install -y crossbuild-essential-arm64+   apt install -y crossbuild-essential-armhf
  
 3. 查看是否安装正确: 3. 查看是否安装正确:
-   aarch64-linux-gnu-gcc -v+   arm-linux-gnueabihf-gcc -v
 系统有打印Gcc 版本即为正常: 系统有打印Gcc 版本即为正常:
  
-{{:pasted:20220719-004327.png}} +{{:pasted:20230823-200954.png}}
-=== GPIO应用编程 === +
-系统下操作GPIO的方式参考[[np-8132-v0a#扩展IO卡使用方法|IO使用方法]] +
-  +
-C参考代码如下: +
- #include <stdio.h>  +
- #include <stdlib.h>  +
- #include <sys/types.h>  +
- #include <sys/stat.h>  +
- #include <fcntl.h>  +
- #include <unistd.h>  +
- #include <string.h>  +
- static char gpio_path[100]; +
-  //设置GPIO方向、高低电平 +
- static int gpio_config(const char *file, const char *value)  +
- {  +
- char config_path[100];  +
- int len;  +
- int fd;  +
- sprintf(config_path, "%s/%s", gpio_path, file);  +
- if (0 > (fd = open(config_path, O_WRONLY)))  +
-+
- perror("open error");  +
- return fd;  +
- }  +
- len = strlen(value);  +
- if (len != write(fd, value, len)) +
- {  +
- perror("write error");  +
- close(fd);  +
- return -1;  +
- }  +
- close(fd);  +
- return 0;  +
- }  +
-  //获取GPIO的方向、电平 +
- static int gpio_get(const char *file) +
- {  +
- char get_path[100];  +
- char buf[10]={"\0"}; +
- int len;  +
- int fd;  +
- sprintf(get_path, "%s/%s", gpio_path, file); +
- if (0 > (fd = open(get_path, O_RDWR))) +
-+
- perror("open error");  +
- return fd;  +
-+
- if ( 0 > read(fd,buf,10)) +
-+
- perror("read error");  +
- return fd;  +
-+
- printf("  %s : %s",file,buf); +
- close(fd);  +
- return 0;  +
-+
- int main(int argc, char *argv[])  +
- {  +
- if (4 != argc)  +
- {  +
- if (3 != argc) +
-+
- fprintf(stderr, "set gpio out : %s <gpio> <out> <value>\n", argv[0]);  +
- fprintf(stderr, "set gpio in  : %s <gpio> <in>\n", argv[0]);  +
- exit(-1);  +
-+
- }  +
- sprintf(gpio_path, "/sys/class/gpio/gpio%s", argv[1]);  +
- if (access(gpio_path, F_OK))  +
- {  +
- printf("%s inexistence,export %s... \n",gpio_path,argv[1]); +
- int fd;  +
- int len;  +
- if (0 > (fd = open("/sys/class/gpio/export", O_WRONLY)))  +
-+
- perror("open error"); exit(-1);  +
- }  +
- len = strlen(argv[1]);  +
- if (len != write(fd, argv[1], len))  +
-+
- perror("write error");  +
- close(fd); +
- exit(-1);  +
- }  +
- close(fd); +
- }  +
- if (gpio_config("direction", argv[2]))  +
- exit(-1);  +
- if ( 0 == strcmp("out",argv[2] ) && argc == 4 ) +
-+
- if(gpio_config("value", argv[3])) +
- exit(-1);  +
-+
- printf("GPIO%s:\n",argv[1]);  +
- if (gpio_get("direction")) +
- exit(-1); +
- if (gpio_get("value")) +
- exit(-1); +
- exit(0);  +
-+
- +
-交叉编译源码: +
- +
-  aarch64-linux-gnu-gcc -o gpio gpio.c +
-   +
- 将编译好的gpio程序使用scp 拷贝到8132 主板上,执行测试: +
- +
-使用方法: +
-  set gpio out : ./gpio <gpio> <out> <value> +
-  set gpio in  : ./gpio <gpio> <in> +
- +
- {{:pasted:20220719-001444.png}} +
- +
-=== Switch应用编程 === +
-参考系统下操作Switch的方法:[[np-8132-v0a#左右拨码开关使用方法|左右拨码开关使用方法]],获取到switch的设备节点为 +
-  /dev/input/event2 +
-  +
-C参考代码如下: +
- +
- #include <unistd.h> +
- #include <fcntl.h> +
- #include <stdio.h> +
- #include <stdlib.h> +
- #include <linux/input.h> +
- #include <sys/select.h> +
- #define INPUT_DEVICE "/dev/input/event2" +
- int main(int argc, char **argv){ +
- int fd; +
- struct input_event event; +
- ssize_t bytesRead; +
- int ret; +
- fd_set readfds; +
- if ( 0 > (fd = open(INPUT_DEVICE,O_RDONLY))) +
-+
- perror("open error");  +
- return fd;  +
-+
- while(1){ +
- FD_ZERO(&readfds); +
- FD_SET(fd,&readfds); +
- ret = select(fd + 1, &readfds, NULL, NULL, NULL); +
- if (ret == -1){ +
- fprintf(stderr,"select call on%s : an error ocurred",argv[1]); +
- break; +
- }  +
- if(FD_ISSET(fd,&readfds)){ +
- bytesRead = read(fd, &event,sizeof(struct input_event)); +
- if(bytesRead == -1 ) +
- fprintf(stderr,"bytesRead :%ld : an error ocurred",bytesRead); +
- }  +
-  +
- if (event.type == EV_KEY && event.code == KEY_RIGHT){ +
- if(event.value == 1) +
- printf("Switch on the right\n"); +
-+
- if (event.type == EV_KEY && event.code == KEY_LEFT){ +
- if(event.value == 1) +
- printf("Switch on the left\n"); +
-+
-+
- close(fd); +
- return EXIT_SUCCESS; +
-+
- +
-交叉编译源码: +
-  aarch64-linux-gnu-gcc -o switch switch.c +
-将编译好的程序使用scp 拷贝到8132 主板上,执行测试,拨动switch打印如下: +
- +
-{{:pasted:20220719-014056.png}} +
- +
-=== Rotary应用编程 === +
-参考系统下操作Rotary的方法:[[np-8132-v0a#十段位编码开关使用方法|编码开关使用方法]],获取到Rotary的设备节点为 +
-  /dev/input/event1 +
-C参考代码如下: +
-  #include <unistd.h> +
- #include <fcntl.h> +
- #include <stdio.h> +
- #include <stdlib.h> +
- #include <linux/input.h> +
- #include <sys/select.h> +
- #define INPUT_DEVICE "/dev/input/event1" +
- int main(int argc, char **argv){ +
- int fd; +
- struct input_event event; +
- ssize_t bytesRead; +
- int ret; +
- fd_set readfds; +
- if ( 0 > (fd = open(INPUT_DEVICE,O_RDONLY))) +
-+
- perror("open error");  +
- return fd;  +
-+
- while(1){ +
- FD_ZERO(&readfds); +
- FD_SET(fd,&readfds); +
- ret = select(fd + 1, &readfds, NULL, NULL, NULL); +
- if (ret == -1){ +
- fprintf(stderr,"select call on%s : an error ocurred",argv[1]); +
- break; +
- }  +
- if(FD_ISSET(fd,&readfds)){ +
- bytesRead = read(fd, &event,sizeof(struct input_event)); +
- if(bytesRead == -1 ) +
- fprintf(stderr,"bytesRead :%ld : an error ocurred",bytesRead); +
- }  +
- if (event.type == EV_ABS && event.code == ABS_X){ +
- printf("Rotary value is : %d \n",event.value); +
-+
-+
- close(fd); +
- return EXIT_SUCCESS; +
-+
-交叉编译源码: +
-  aarch64-linux-gnu-gcc -o rotary rotary.c +
-将编译好的程序使用scp 拷贝到8132 主板上,执行测试,拨动rotary打印如下 +
- +
-{{:pasted:20220719-020037.png}} +
-=== CAN应用编程 === +
-参考系统下操作CANBUS的方法:[[np-8132-v0a#CANBUS使用方法|CANBUS使用方法]],设置can: +
-  ip link set can0 down +
-  ip link set can0 type can bitrate 125000 +
-  ip link set can0 up +
-  ip link set can1 down +
-  ip link set can1 type can bitrate 125000 +
-  ip link set can1 up +
-   +
- C参考代码如下: +
- +
- #include <stdio.h>  +
- #include <stdlib.h>  +
- #include <string.h>  +
- #include <unistd.h>  +
- #include <sys/ioctl.h>  +
- #include <sys/socket.h>  +
- #include <linux/can.h>  +
- #include <linux/can/raw.h>  +
- #include <net/if.h>  +
- int main(int argc, char **argv)  +
- {  +
- struct ifreq ifr_recv = {0}; +
- struct ifreq ifr_send = {0}; +
- struct sockaddr_can addr_recv = {0};  +
- struct sockaddr_can addr_send = {0};  +
- struct can_frame frame_recv = {0};  +
- struct can_frame frame_send = {0}; +
- int sockfd_r = -1; +
- int sockfd_s = -1; +
- int ret, i;  +
- if ( 3 != argc ) +
-+
- fprintf(stderr, "user : %s <can_recv> <can_send>\n", argv[0]); +
- exit(EXIT_FAILURE);  +
- }  +
- if ( 0 > (sockfd_r = socket(PF_CAN, SOCK_RAW, CAN_RAW)))  +
- {  +
- perror("socket error");  +
- exit(EXIT_FAILURE);  +
- }  +
- if ( 0 > (sockfd_s = socket(PF_CAN, SOCK_RAW, CAN_RAW)))  +
- {  +
- perror("socket error");  +
- exit(EXIT_FAILURE);  +
- }  +
- strcpy(ifr_recv.ifr_name, argv[1]);  +
- ioctl(sockfd_r, SIOCGIFINDEX, &ifr_recv);  +
- addr_recv.can_family = AF_CAN;  +
- addr_recv.can_ifindex = ifr_recv.ifr_ifindex;  +
- strcpy(ifr_send.ifr_name, argv[2]);  +
- ioctl(sockfd_s, SIOCGIFINDEX, &ifr_send);  +
- addr_send.can_family = AF_CAN;  +
- addr_send.can_ifindex = ifr_send.ifr_ifindex; +
- ret = bind(sockfd_r, (struct sockaddr *)&addr_recv, sizeof(addr_recv));  +
- if (0 > ret)  +
- {  +
- perror("bind error");  +
- close(sockfd_r);  +
- exit(EXIT_FAILURE); +
- }  +
- ret = bind(sockfd_s, (struct sockaddr *)&addr_send, sizeof(addr_send));  +
- if (0 > ret)  +
- {  +
- perror("bind error");  +
- close(sockfd_s);  +
- exit(EXIT_FAILURE); +
- }  +
- setsockopt(sockfd_s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);  +
- frame_send.data[0] = 0xAA;  +
- frame_send.data[1] = 0xBB;  +
- frame_send.data[2] = 0xCC;  +
- frame_send.data[3] = 0xDD;  +
- frame_send.data[4] = 0xEE;  +
- frame_send.data[5] = 0xFF;  +
- frame_send.data[6] = 0x11;  +
- frame_send.data[7] = 0x22;  +
- frame_send.can_dlc = 8;  +
- frame_send.can_id = 0x123; +
- while(1)  +
- {  +
- ret = write(sockfd_s, &frame_send, sizeof(frame_send));  +
- if(sizeof(frame_send) != ret)  +
- {   +
- perror("write error");  +
- goto out;  +
- }  +
- printf("%s send :[%d]",ifr_send.ifr_name,frame_send.can_dlc); +
- for (i = 0; i < frame_send.can_dlc; i++)  +
- printf("%02x ", frame_send.data[i]); +
- sleep(1);  +
- if (0 > read(sockfd_r, &frame_recv, sizeof(struct can_frame)))  +
-+
- perror("read error"); +
- break;  +
- }  +
- if (frame_recv.can_id & CAN_ERR_FLAG)  +
- {  +
- printf("Error frame_recv!\n");  +
- break;  +
- }  +
- printf("\n%s recv :[%d]", ifr_recv.ifr_name,frame_recv.can_dlc);  +
- for (i = 0; i < frame_recv.can_dlc; i++)  +
- printf("%02x ", frame_recv.data[i]);  +
- printf("\n");  +
- }  +
- out:  +
- close(sockfd_r);  +
- close(sockfd_s);  +
- exit(EXIT_SUCCESS);  +
-+
-交叉编译源码: +
-  aarch64-linux-gnu-gcc -o cantest cantest.c +
-将编译好的程序使用scp 拷贝到8132 主板上,对接CAN0-CAN1执行测试:+
  
-{{:pasted:20220720-004229.png}} 
  
  
打印/导出