==== Linux 编程指南 ====
=== GPIO 应用编程 ===
C参考代码如下:
#include
#include
#include
#include
#include
#include
#include
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 \n", argv[0]);
fprintf(stderr, "set gpio in : %s \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拷贝到 r39s2 主板上,执行测试:
使用方法:
0:./gpio 3
1:./gpio 1
{{:arm:rk3399:linux:r39s2_gpio.c.png?600|}}
=== UART 应用编程 ===
系统下操作 UART 的测试串口,以 J_RS232 TX3\RX3 测试为例:
J_RS232 TX3\RX3 设备节点为:
/dev/ttysWK2
C参考UART高低电平输入代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
int set_opt(int,int,int,char,int);
void main(){
int fd,nByte;
char *uart3 = "/dev/ttyS2";
char bufferR[2];
char bufferW[2];
memset(bufferR, '\0', 2);
memset(bufferW, '\0', 2);
if((fd=open(uart3,O_RDWR,0777))<0)
{
printf("failed\n");
}
else{
printf("success\n");
set_opt(fd, 115200, 8, 'N', 1);
}
while(1){
nByte = 0;
memset(bufferR, '\0', 2);
memset(bufferW, '\0', 2);
// printf("hello\n");
if((nByte = read(fd, bufferR, 1)) == 1){ //MCU串口发送接收都是单字节(单字符)函数
printf("receive:%c\n",bufferR[0]);
bufferW[0] = 'A';
write(fd,bufferW,1); //串口发送单字节(单字符) buffer[0] = data
memset(bufferR, '\0', 2);
memset(bufferW, '\0', 2);
nByte = 0;
}
}
close(fd);
}
//串口通用初始化函数
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio,oldtio;//定义结构体newtio和oldtio
//将原串口的数据取到oldtio
if ( tcgetattr( fd,&oldtio) != 0) {
perror("SetupSerial 1");
return -1;
}
//将newio清零和设置c_cflag
bzero( &newtio, sizeof( newtio ) );
newtio.c_cflag |= CLOCAL | CREAD;//使能接收和忽略控制线
newtio.c_cflag &= ~CSIZE;
//设置数据位
switch( nBits )
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
//设置校验位
switch( nEvent )
{
//偶校验
case 'O':
newtio.c_cflag |= PARENB;//使能奇偶校验
newtio.c_cflag |= PARODD;//偶校验
newtio.c_iflag |= (INPCK | ISTRIP);//输入校验并忽略第八位
break;
case 'E':
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;//取消偶校验(置零偶校验位),开启奇校验
break;
case 'N':
newtio.c_cflag &= ~PARENB;//不进行奇偶校验
break;
}
//设置波特率
switch( nSpeed )
{
case 2400:
cfsetispeed(&newtio, B2400);
cfsetospeed(&newtio, B2400);
break;
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
case 460800:
cfsetispeed(&newtio, B460800);
cfsetospeed(&newtio, B460800);
break;
default:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
}
//设置停止位
if( nStop == 1 )
newtio.c_cflag &= ~CSTOPB;//一位停止位
else if ( nStop == 2 )
newtio.c_cflag |= CSTOPB;//两位停止位
newtio.c_cc[VTIME] = 0;//不设置读取超时
newtio.c_cc[VMIN] = 0;//读取最小字符数为0
tcflush(fd,TCIFLUSH);//清空缓冲区
//使配置生效
if((tcsetattr(fd,TCSANOW,&newtio))!=0)
{
perror("com set error");
return -1;
}
// printf("set done!\n\r");
return 0;
}
交叉编译源码:
aarch64-linux-gnu-gcc -o uart uart.c
将编译好的程序使用 scp 拷贝到 3399 主板上,执行测试:
{{:arm:rk3399:linux:r39s2_uart.c.png?600|}}
=== KEY 应用编程 ===
参考系统下操作Key的方法,获取到key的设备节点为
/dev/input/event2
C参考代码如下:
#include
#include
#include
#include
#include
#include
#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.value == 0 || event.value == 1))
{
printf("key %s\n",(event.value) ? "pressed" : "released");
}
}
close(fd);
return EXIT_SUCCESS;
}
交叉编译源码:
aarch64-linux-gnu-gcc -o key key.c
将编译好的程序使用 scp 拷贝到 r39s2 主板上,执行测试,按动 key 打印如下:
{{:arm:rk3399:linux:key编程.png?600|}}
*按下按键时显示:key pressed
*松开按键时显示:key released