基于LS2K1000LA的基础教程

by 南京工业大学 孙冬梅

于 2024.4.25

一、目的

目的:基于loongarch 架构 龙芯派基本上手 教程

  • GPIO操作:读取与写入

  • UART操作 : 基于modbus协议的数据读取

  • I2C操作: 基于I2C总线光照度传感器数据读取

  • 关键技术:

    • 基于modbus的数据协议采集数据
    • 基于mqtt 的远程数据传输协议
    • linux下的脚本执行

二、平台

1.硬件平台

LS2K1000LA 龙芯派开发板,接口引脚如图 2-1所示。
在这里插入图片描述
​ 图2-1 龙芯派 GPIO外设接口功能图

基于龙芯派 GPIO外设接口, 进行电路 扩展。

  • 电源转换: 12V - 5V ; 5V - 3.3V
  • UART 总线 接口
    • UART3
    • UART4
    • UART5
  • I2C 0总线接口
    • BH1750光照度传感器
  • GPIO 和 LED
2.软件平台

运行环境:loongnix 操作系统

开发环境:x86_64 主机 ,基于linux 5.15 内核的ubuntu20.04 操作系统

三、测试

0.开发板开机及编译器配置

0.1 开发板控制台

使用mobaxterm 与开发板 串口 连接 115200; 用户 root 登录 ,无密码
在这里插入图片描述

在串口控制台配置eth1 IP 地址192.168.1.254; 注意:这里eth1是靠近耳机孔的网口。使用命令:

 ifconfig eth1 192.168.1.254

在这里插入图片描述

将自己本机 IP地址设置为 192.168.1.66,网线连接本机和开发板,在开发板控制台中使用ping测试连通性

在这里插入图片描述

如果使用路由器,以上配置IP步骤可省略,直接将开发板连接到路由器,不用修改任何IP地址;本机PC也连接到路由器;找到自己PC的IP地址,找到连接到路由器开发板的IP地址。

使用mobaxterm 用ssh 连接开发板的IP地址( 192.168.1.254 使用路由器的 不是这个,要用ifconfig查询下) 端口22

在这里插入图片描述

连接成功后,可进行文件查看,复制粘贴等:

在这里插入图片描述

至此,开发板控制台 为 串口控制台(只能有一个)、SSH 远程登录 控制台(可以开很多个,类似 ubantu 中的 terminal)。

0.2 虚拟机编译器配置

QT编译工具安装

资料包提供了编译应用程序的交叉工具链, 主要针对QT应用
下载LoongOS-glibc-x86_64-loongos-desktop-image-loongarch64-ls2k1000-toolchain-v0.1.sh,并执行,具体流程如下:

注意安装目录 : /home/toolchain

loongson@ubuntu:~/Downloads$ sudo sh LoongOS-glibc-x86_64-loongos-desktop-image-loongarch64-ls2k1000-toolchain-v0.1.sh
[sudo] password for loongson: 
LoongOS SDK installer version v0.1
==================================
Enter target directory for SDK (default: /usr/local/oecore-x86_64): /home/toolchain
You are about to install the SDK to "/home/toolchain". Proceed [Y/n]? y
Extracting SDK...............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................done
Setting it up...done
SDK has been successfully set up and is ready to be used.
Each time you wish to use the SDK in a new shell session, you need to source the environment setup script e.g.
 $ . /home/toolchain/environment-setup-loongarch64-Loongson-linux

使用之前 先添加环境变量,查看版本 :

loongson@ubuntu:~/Downloads$ source /home/toolchain/environment-setup-loongarch64-Loongson-linux
loongson@ubuntu:~/Downloads$ qmake -v   #查看qmake版本
QMake version 3.1
Using Qt version 5.15.3 in /home/toolchain/sysroots/loongarch64-Loongson-linux/usr/lib64

在这里插入图片描述

编写helloworld.c 文件

/*helloworld.c*/
#include <stdio.h>
void main()
{
char *str ="Hello World";
printf("%s\n",str);
}

用新安装的编译工具进行编译

loongson@ubuntu:~/test$ $CC -o helloworld helloworld.c 

将helloworld 从开发板控制台下载下开发板运行,运行 命令为:

./helloworld

在这里插入图片描述

1。将在虚拟中编译好的 可执行文件拖拽到 mobaxterm(已经通过ssh连接到龙芯2K开发板)的资源管理器
2。修改可执行文件的属性为 可读写 chmod 777 gpio_write
3。运行可执行文件 ./gpio_write

下面进行编程,分为简单应用编译和外设接口编程2部分

例程全部参考《嵌入式Linux系统设计及应用-基于国产龙芯SOC(智龙开发板)3.1.0》

1. 简单应用编程

1.helloworld.c

功能: 打印出 helloworld

#include <stdio.h>
int main(void)
{
	printf("Hello World!\n");
	return 0;
}

编译命令:

 $CC -o helloworld helloworld.c  

将helloworld下载开发板运行,正常运行

2. fileio 文件操作

功能: 调用open函数 读写方式打开文件 写入"hello,I’m Loongson,This is file io test!" 后读出并打印

/*fileio.c  */

命令:

运行 make 生成 fileio , 下载到开发板运行。
运行 make clean ,清除当前目标文件。

将fileio下载开发板运行,正常运行

3.processctl 进程控制

功能:

getpid 获取 当前进程的ID

fork 创建新进程

getpid.c
$CC getpid.c -o  getpid 

fork.c
$CC fork.c -o fork

/*Linux_进程替换(execl、execlp、execv、execle)  替换函数(unistd.h)*/
execl.c ececlp.c ececv.c execve.c 这4个是进程替换函数不进行测试了

替换函数总结

函数名 参数传递形式 路径 是否导入环境变量
execl 列表 需要可执行程序路径 不导入 使用当前环境变量
execlp 列表 默认在环境变量中找 不导入 使用当前环境变量
execle 列表 需要可执行程序路径 导入 使用导入的环境变量
execv 数组 需要可执行程序路径 不导入 使用当前环境变量
execvp 数组 默认在环境变量中找 不导入 使用当前环境变量
execve 数组 需要可执行程序路径 导入 使用导入的环境变量

进程替换注意事项
1.进程替换不会创建新进程,因为进程替换只是将该进程的数据替换为指定的可执行程序。而进程PCB没有改变,所以不是新的进程,进程替换后不会发生进程pid改变。

2.进程替换后,如果替换成功后则替换函数下的代码不会执行,因为进程替换是覆盖式的替换,替换成功后进程原来的代码就消失了。同理在进程替换失败后会执行替换函数后的代码

3.进程替换函数在进程替换成功后不返回,函数的返回值表示替换失败

4.进程替换成功后,退出码为替换后的进程的退出码

4.processcomu 进程间通讯

功能:

pipe 创建无名管道,如果成功则打开两个文件描述符

pipe_rw 无名管道读写

fifo_read 读取管道数据;要将读进程在后台运行。首先启动读管道, ./fifo_read &

fifo_write 写数据到管道 与fifo_read组合运行

msg 使用消息队列进行进程间通信

shadd 创建一个共享内存区,将其映射到本进程中,最后再解除映射

pipe.c
$CC  pipe.c -o  pipe 

pipe_rw.c
$CC pipe_rw.c -o  pipe_rw 

fifo_read.c
$CC fifo_read.c-o fifo_read

fifo_write.c
$CC fifo_write.c -o fifo_write

msg.c
$CC msg.c -o msg

shmadd.c
$CC shmadd.c -o shmadd

5. threadapp 线程应用

thread 创建两个线程,第一个线程是在程序运行到中途时调用pthread_exit 主动退出,然后睡眠 2s;第二个线程正常运行退出。

pthread 创建两个线程,第一个线程的线程属性设置为绑定、分离属性;
第二个线程设置为默认的属性,即非绑定、非分离属性。

sem 使用信号量的机制来对计数变量 lock_var 操作

mutex 快速互斥锁来实现对计数变量 lock_var 操作

thread.c
$CC thread.c -o thread -pthread //要加上 -pthread 因为 Linux 系统中本身并不包含线程库

pthread.c
$CC pthread.c -o pthread -pthread //要加上 -pthread 因为 Linux 系统中本身并不包含线程库

sem.c
$CC sem.c -o sem -pthread 

mutex.c
$CC mutex.c -o mutex -pthread 

6. net 网络编程应用

功能:

client 先PC机运行TCPUDPdebug程序 开启tcp服务器 再开启开发板tcp连接服务器, 命令: ./client 目的IP 目的端口号

server 先开启开发板tcp服务器 命令: ./server 源IP ,PC机运行TCPUDPdebug程序 开启tcp客户端,连接开发板的服务器

client.c
$CC client.c -o client

server  
$CC client.c -o client

2. 外设编程

1、GPIO 操作
控制台操作
# echo 50 > /sys/class/gpio/export     //将50引脚导出
# echo 46 > /sys/class/gpio/export     //将46引脚导出
# echo out > /sys/class/gpio/gpio50/direction   //设置50为输出
# echo in > /sys/class/gpio/gpio46/direction    // 设置46 为输入
# echo 0 > /sys/class/gpio/gpio5/value //输出低电平 
# echo 1 > /sys/class/gpio/gpio5/value //输出高电平 
#cat /sys/class/gpio/gpio46/value   //查看 GPIO 排列序号为 46的 GPIO 电平
1
编程操作

功能:

gpio_read.c 读取GPIO40 命令 gpio_read 46

gpio_write.c 输出到 GPIO41 gpio_write 50 0 ./gpio_write 50 1 GPIO50 输出0 1

gpip_poll.c 外部(poll方式) gpio_poll 46 50 读取GPIO46 输出到 GPIO50

gpio_read.c
$CC gpio_read.c -o gpio_read

gpio_write.c  
$CC gpio_write.c -o gpio_write

gpip_poll.c
$CC gpip_poll.c -o gpip_poll
2、uart

sttyS1, 对应图中的UART3

sttyS2, 对应图中的UART4

sttyS3, 对应图中的UART5

控制台操作
root@ls3a5000:~# stty -F /dev/ttyS1 speed 115200 cs8
115200
root@ls3a5000:~# echo 123 > /dev/ttyS1
root@ls3a5000:~#cat /dev/ttyS1  //等待接收字符串

一个个的测试下来, UART3 4 5没有问题 ttYS1/2/3 可以用 , ttYS1/2/3对应UART3 4 5 ,测试UART5 OK

编程操作
uart.c serial.c serial.h

运行 make 生成 uart, 下载到开发板运行。
运行 make clean ,清除当前目标文件。

将uart下载开发板运行,正常运行

PC 通过串口硬件连接 开发板 ttyS1 ,运行 uart 打印如下信息“Hello! I am Loongson!”,在 PC机串口助手中输入“Hello,I am Sundm75”,则此字符通过 uart1 传入开发板

3、I2C
控制台操作

将24C02 连接到 i2c1, 地址0x50,进行探测 i2cdetect -r -r 1

在这里插入图片描述

读取所有数据 i2cdump -y 1 0x50

在这里插入图片描述

数据设置 i2cset -y 1 0x50 0x01 0x5A

在这里插入图片描述

DS3231 连接到 i2c0, 地址0x68,进行探测 i2cdetect -r -r 1

在这里插入图片描述

读取所有数据 i2cdump -y 0 0x68

在这里插入图片描述

编程操作

测试bh1750

BH1750是一种用于两线式串行总线接口的数字型光强度传感器集成电路。这种集成电路可以根据收集的光线强度数据来调整液晶或者键盘背景灯的亮度。利用它的高分辨率可以探测较大范围的光强度变化。BH1750的内部由光敏二极管、运算放大器、ADC采集、晶振等组成。对应广泛的输入光范围(相当于1-65535lx),最小误差变动在土20%,而且受红外线影响很小。

1、采用ROHM原装BH1750FVI芯片
 2、光照度范围: 0-655351x,传感器内置16bitAD转换器直接数字输出,省略复杂计算)省略标定
 3、内部包含通信电平转换,与5V单片机I0连接,支持STM32/51/ardunio
 4、XH2.54接口连接线,方便客户DIY
 5、小体积,广泛应用于室内光照检测、蔬菜、苗圃、温室大棚

连接到 i2c0

BH1750_Addr (7位地址) 0x23 先探测: i2cdetect -r -y 0

在这里插入图片描述

发送 0x01 power on

发送 0x10 启动连续测量 精度 1lx resolution 测量时间 120ms

然后读取

读取光照度 代码:

/*test_bh1750.c*/

命令:

运行 make 生成 test_bh1750, 下载到开发板运行。
运行 make clean ,清除当前目标文件。

将 test_bh1750下载开发板运行,正常运行

在这里插入图片描述

3. 驱动编程

1. mqtt 数据上传云

参考 一套极简的MQTT使用接口EasyMqttClient

在Linux环境下使用本项目:

  • 克隆本项目
 git clone https://github.com/Yangyuanxin/EasyMqttClient
  • 修改编译参数

CPPFLAGS : 预处理器需要的选项 如:-I (大写i指定头文件路径)
CFLAGS:编译的时候使用的参数 –Wall –g -c
LDFLAGS :链接库使用的选项 –L -l (大写L指定动态库的路径,小写L指定动态库的名称)

  • 修改makefile :注释前面14行

  • 运行 make all

生成 a.out ,下载到开发板可运行

2、modbus数据读取

1.首先在github上获取源代码

git clone https://github.com/stephane/libmodbus

2.创建安装目录

开发板/home/loongson/libmodbus/install ,要创建这个新目录

cd ~
mkdir libmodbus
chmod 777 libmodbus
mkdir install
chmod 777 install

3.配置编译选项

运行 ./autogen.sh 生成 configure 脚本

安装automake工具,执行下面命令安装

sudo apt install autoconf automake libtool

配置工具链: ./configure --host=[交叉编译工具链前缀] --enable-static --prefix=[安装路径] /install/

./configure --host=loongarch64-Loongson-linux --enable-static --prefix=./configure --prefix=/home/loongson/libmodbus/install 

编译

make
make install

4.打包复制

成功后 将 libmodbus/install 文件打包

tar cvf libmodbus.tar install

libmodbus.tar 复制到开发板上解压

tar xvf libmodbus.tar

将install/lib文件夹下的libmodbus.so、libmodbus.so.5、libmodbus.so.5.1.0复制到开发板的/usr/lib 和/usr/lib64目录下。

cd /home/loongson/libmodbus/install/lib/
cp libmodbus.so* /usr/lib
cp libmodbus.so* /usr/lib64

5、测试程序

1.创建一个modbusrtu_test.c文件

2.将install/include/modbus/中的头文件复制到与ModbusRTU_Test.c文件一个目录中

3.编译

$CC -o modbusrtu_test modbusrtu_test.c  -L /home/loongson/libmodbus/install/lib/ -lmodbus 

4.将可执行文件复制到ARM板下,运行测试

1)复制赋权限

2)UART ttyS3使用Modbus Slave模拟个设备 设置  slaveID=1  通讯参数: 115200 8 N 1

3)运行

四、基于qt 编写界面和功能

1.QT下载及编译器配置

1、下载 Qt5: 5.12 LTS 长期支持版本

2、开始安装qt

3、安装完成后 编译器配置

添加 C 编译器 和 C++编译器

/home/toolchain/sysroots/x86_64-loongsonsdk-linux/usr/bin/loongarch64-Loongson-linux-gcc

/home/toolchain/sysroots/x86_64-loongsonsdk-linux/usr/bin/loongarch64-Loongson-linux-g++

在 tools 菜单下,选择 options , 如下图添加

在这里插入图片描述

再修改 qmake

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. QT开发

打开例程 analogclock, 选择LA 工具,编译后生成 analogclock
在这里插入图片描述

下载到开发板上,修改权限后运行正常。

在这里插入图片描述

五、开机自启动

自己写一个shell脚本
将写好的脚本(.sh文件)放到目录 /etc/profile.d/ 下,系统启动root登录后就会自动执行该目录下的所有shell脚本。本脚本自启动 /home/loongson/loongsonapp/目录下的 analogclock 可执行文件。

loongsonapp.sh 文件,

#!/bin/bash
echo "loongson_gateway==================================================================!"
/home/loongson/loongsonapp/analogclock

注意修改文件名加 zz ,因为该目录下的所有shell脚本是按照文件名顺序执行,将文件放到最后从而保证当 QT插件运行完后再执行

六、关机 (不可直接拔电源 )

在开发板控制台中输入命令: poweroff, 等命令显示完毕,就能拔电源 了

在这里插入图片描述

七、结论

本文首先描述了基于LS2K1000LA开发板安装编译器进行交叉编译出可执行文件的过程;讲解了GPIO操作、UART操作、I2C三种外设操作的基本方法;说明了QT和相关编译器进行界面开发流程;最后基于开源库libmodbus和mqttclient实现了在LS2K1000LA开发板的移植,从而实现modbus协议数据读取和向云端传数。

源码下载

参考文献

  1. 孙冬梅. 嵌入式Linux系统设计及应用-基于国产龙芯SOC(LS1C300).[M] .北京:清华大学出版社.
  2. 孙冬梅.龙芯嵌入式系统原理与应用开发(LS1B300) . [M]. 北京:人民邮电出版社 .
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐