本文从搭建环境开始,step by step教大家使用XR806实现驱动SPI屏幕(ST7735S驱动),并连接WiFi实现ntp对时,最终实现把时间显示到屏幕上。
#1. 搭建开发环境
1. 安装编译环境所需的依赖包
基于ubuntu 20.04,按照鸿蒙官方给的开发环境搭建教程安装以下依赖包
-
安装repo工具:
curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > repo
chmod a+x repo
sudo mv repo /usr/local/bin/ -
安装request工具,如果已经安装过可以忽略:
pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests
-
安装必要的依赖,由于要安装的包比较多,建议先更换为适合自己所在地区的最快的软件源,相关方法可以搜索"ubuntu apt 换源"。
sudo apt update
sudo apt install -y git git-lfs build-essential gcc g++ make zlib* libffi-dev e2fsprogs pkg-config flex bison perl bc openssl libssl-dev libelf-dev libc6-dev-amd64 binutils binutils-dev libdwarf-dev u-boot-tools mtd-utils gcc-arm-linux-gnueabi cpio device-tree-compiler libncurses5-dev
-
安装hb编译工具,注意这里需要指定版本0.4.3,使用新版编译工具会报错。
sudo -H python3 -m pip install ohos-build==0.4.3
-
安装llvm
wget https://repo.huaweicloud.com/harmonyos/compiler/clang/9.0.0-36191/linux/llvm-linux-9.0.0-36191.tar
tar -zxvf llvm-linux-9.0.0-36191.tar -C ~/
vim ~/.bashrc将这句话添加到~/.bashrc末尾:
export PATH=~/llvm/bin:$PATH
然后:wq回车保存退出source vim ~/.bashrc
##2. 下载源码,按照官方给的下载方法操作即可
-
首先创建一个文件夹用于接收源码,并作为之后编译工程的目录
mkdir xr806_openharmony
cd xr806_openharmony- 然后将git的用户配置自己的gitee用户名和邮箱
git config --global user.name "yourname"
git config --global user.email "your-email-address"
git config --global credential.helper store- 接着初始化代码仓库
repo init -u https://gitee.com/openharmony-sig/manifest.git -b OpenHarmony_1.0.1_release --no-repo-verify -m devboard_xr806.xml
先不要着急同步代码,由于鸿蒙官方仓库暂时无法下载xr806的设备代码,需要修改代码同步配置文件指向备份下载仓库,使用文件管理器打开以下代码配置文件
gedit ~/xr806_openharmony/.repo/manifests/devboard_xr806.xml
定位到第5行,插入一行新的配置
定位到第34行,将sig修改为sig2
定位到第116行,同样将sig修改为sig2
保存以上修改好的文件。
4. 开始同步下载代码,该过程大约需要6分钟,可以去喝口茶休息一会.
repo sync -c
repo forall -c 'git lfs pull'
5. 下载完代码后测试hb编译工具是否可行,在代码根目录输入hb -
,会有以下提示:
##3. 下载编译工具链:使用浏览器下载以下文件
https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
下载完成后解压放到~/tools文件夹内:
mkdir ~/tools
tar -jxvf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 -C ~/tools
#2. 执行首次编译,初始化编译环境
#(1)进入原生SDK目录
cd device/xradio/xr806/xr_skylark
#(2)复制配置文件
cp project/demo/audio_demo/gcc/defconfig .config
#(3)图形化界面配置
make menuconfig
#(4)清除旧配置
make build_clean
#(5)根据配置生成静态库和全局头文件
make lib -j
#(6)返回Harmony根目录
cd -
#(7)选择wifi_skylark
hb set
#(8)编译,后续不需要重新配置
hb build -f
(3)图形化界面配置
make menuconfig
(7)选择wifi_skylark
hb set
(8)编译,后续不需要重新配置
hb build -f
#3. 屏幕与开发板之间的连接:
编号 | 屏幕端 | 开发板端 |
---|---|---|
1 | VCC | 3V3 |
2 | GND | GND |
3 | CS | PB6 |
4 | RESET | PB15 |
5 | A0 | PB14 |
6 | SDA | PB4 |
7 | SCK | PB7 |
8 | LED | PB3 |
LCD屏幕:ST7735S
1.VCC---3V3
2.GND---GND
3.CS ---PB06
4.RESET---PB15
5.DC(A0)---PB14
6.MOSI(SDA)---PB04
7.CLK(SCK)---PB07
8.LED---PB03
#4. 编写我们的代码
##1. 创建一个工程
首先进入ohosdemo文件夹,新建一个工程文件夹lcd_weather_clock,并配置好ohosdemo中的BUILD.gn,添加我们新建的工程lcd_weather_clock。
cd ~/xr806_openharmony/device/xradio/xr806/ohosdemo
mkdir lcd_weather_clock
gedit BUILD.gn
其中 ~/xr806_openharmony/device/xradio/xr806/ohosdemo/BUILD.gn 主要内容如下(篇幅有限省略前面的注释):
group("ohosdemo") {
deps = [
#"hello_demo:app_hello",
#"iot_peripheral:app_peripheral",
#"wlan_demo:app_WlanTest",
"lcd_weather_clock:app_lcd_weather_clock",
]
}
进入新建的工程文件夹,新建include文件夹用于存放头文件(.h),新建src文件夹用于存放源文件(.c),新建BUILD.gn
cd lcd_weather_clock
mkdir include
mkdir src
gedit BUILD.gn
其中 /home/starsky/xr806_openharmony/device/xradio/xr806/ohosdemo/lcd_weather_clock/BUILD.gn 主要内容如下(篇幅有限省略前面的注释):
import("//device/xradio/xr806/liteos_m/config.gni")
static_library("app_lcd_weather_clock") {
configs = []
sources = [
"src/main.c",
"src/my_wifi.c",
"src/st7735s.c",
]
cflags = board_cflags
include_dirs = board_include_dirs
include_dirs += [
"//kernel/liteos_m/kernel/arch/include",
"include",
"//utils/native/lite/include",
"//foundation/communication/wifi_lite/interfaces/wifiservice",
"//base/iot_hardware/peripheral/interfaces/kits",
"//device/xradio/xr806/xr_skylark/include/net/sntp",
]
}
##2. 编写代码实现相应的功能
该代码主要实现驱动ST7735S屏幕,连接到指定的WiFi,设定sntp服务器并自动对时,然后将时间和日期显示到LCD显示屏幕上。由于篇幅有限此处不展示所有代码,只对关键代码进行说,完整代码与工程文件参考文末的gitee仓库地址。
####1.SPI初始化代码
注意SPI频率以及模式的设定
static void spi_init(void)
{
printf("spi_init started.\r\n");
SPI_Global_Config spi_param;
spi_param.cs_level = 0;
spi_param.mclk = (48 * 1000 * 1000);
HAL_SPI_Init(SPI0, &spi_param);
SPI_Config spi_Config;
HAL_Status ret = HAL_OK;
spi_Config.firstBit = SPI_TCTRL_FBS_MSB; //
//SPI_LITTLEENDIAN;//第一字节 SPI_LITTLEENDIAN,SPI_BIGENDIAN
spi_Config.mode = SPI_CTRL_MODE_MASTER;
//SPI_MODE_MASTER;//SPI_MODE_SLAVE 从,SPI_MODE_MASTER 主
spi_Config.opMode = SPI_OPERATION_MODE_POLL;
spi_Config.sclk = (24 * 1000 * 1000);
spi_Config.sclkMode = SPI_SCLK_Mode0;
printf("spi open...\r\n");
ret = HAL_SPI_Open(SPI0, SPI_TCTRL_SS_SEL_SS0, &spi_Config, 5000);
if (ret != HAL_OK)
{
printf("spi open failed");
return;
}
HAL_SPI_Config(SPI0, SPI_ATTRIBUTION_IO_MODE, SPI_IO_MODE_NORMAL);
printf("spi demo over.\r\n");
return;
}
####2. GPIO初始化函数
注意,这里设定GPIO的模式以及设定GPIO输出电平必须要使用HAL库的函数,使用IoTGpioInit类函数无法正常驱动屏幕。
static void gpio_init(void)
{
GPIO_InitParam param;
param.driving = GPIO_DRIVING_LEVEL_1;
param.mode = GPIOx_Pn_F1_OUTPUT;
param.pull = GPIO_PULL_NONE;
HAL_GPIO_Init(GPIO_PORT_A, GPIO_PIN_21, ¶m);//led灯对应IO
HAL_GPIO_Init(GPIO_PORT_B, GPIO_PIN_15, ¶m);//OLED RES
HAL_GPIO_Init(GPIO_PORT_B, GPIO_PIN_14, ¶m);//OLED DC
HAL_GPIO_Init(GPIO_PORT_B, GPIO_PIN_3, ¶m);//OLED LED
HAL_GPIO_WritePin(GPIO_PORT_B,GPIO_PIN_3,GPIO_PIN_HIGH);
HAL_GPIO_WritePin(GPIO_PORT_A, GPIO_PIN_21,GPIO_PIN_HIGH);
IoTGpioSetIsrMode(KEY1_PIN, IOT_INT_TYPE_EDGE, IOT_GPIO_EDGE_FALL_LEVEL_LOW);
IoTGpioRegisterIsrFunc(KEY1_PIN, IOT_INT_TYPE_EDGE, IOT_GPIO_EDGE_FALL_LEVEL_LOW, IotGpioIrq, 0);
}
####3.设定sntp服务器以及显示日期与时间
struct sntp_arg{
char *server_name; /* remote server name, if this is not NULL, this will be preferred. */
int recv_timeout; /* the receive timeout from ntp server */
uint8_t retry_times; /* the retry times when receiver timeout */
};
static void MainThread(void *arg)
{
struct timeval tv;
struct tm *my_tm;
struct sntp_arg ntp_arg;
char ntp_server_name[24] = "time1.aliyun.com";
char lcd_buffer[64] = {0x00};
setenv("TZ", "CST-8", 1);
tzset();
printf("MainThread start\r\n");
wifi_device_connect();
ntp_arg.server_name = ntp_server_name;
ntp_arg.recv_timeout = 100;
ntp_arg.retry_times = 3;
sntp_set_server(0,ntp_server_name);
sntp_get_time(&ntp_arg, &tv);
gpio_init();
spi_init();
LCD_Init();
printf("after lcd_init\r\n");
sntp_get_time(&ntp_arg, &tv);
settimeofday(&tv, "CST-8");
LCD_Clear(LIGHTBLUE);
BACK_COLOR = LIGHTBLUE;
while (1)
{
POINT_COLOR = GREEN;
gettimeofday(&tv, NULL);
my_tm = localtime(&(tv.tv_sec));
strftime(lcd_buffer, sizeof(lcd_buffer), "%F %a", my_tm);
LCD_Fill(1, 1, 128,20,BACK_COLOR);
LCD_ShowString(1, 1, 16,(uint8_t *)lcd_buffer );
strftime(lcd_buffer, sizeof(lcd_buffer), "%T", my_tm);
LCD_Fill(1, 20, 80,40,BACK_COLOR);
LCD_ShowString(1, 20, 16, (uint8_t *)lcd_buffer);
if(my_tm->tm_hour%6 == 0 && my_tm->tm_sec==0)
{
// 每隔6小时执行一次对时
sntp_get_time(&ntp_arg, &tv);
settimeofday(&tv, "CST-8");
}
OS_MSleep(500);
}
}
####4.设定WiFi账号与密码
请修改my_wifi.c开头的宏定义为自己的WiFi账号密码。
#5. 编译并烧录
##1.编译固件
执行以下命令,当没有报错的时候就是编译成功。
cd ~/xr806_openharmony
hb build -f
##2.接线
将开发板按照上述GPIO口定义连接好屏幕,并使用数据线将开发板连接到电脑
执行 ls /dev/ttyUSB* 查看连接是否成功。
执行以下命令将当前用户加入串口所在的组,以获取串口的读写权限。
sudo usermod -a -G dialout $USER
执行完成后需要重启系统生效,重启前注意保存自己打开的文档等工作内容。
如果不想重启,也可以使用以下命令赋予用户读写串口权限。
sudo chmod 0777 /dev/ttyUSB0
##3.设置下载工具的配置
进入下载固件的工具目录
cd ~/xr806_openharmony/device/xradio/xr806/xr_skylark/tools
gedit settings.ini
主要修改两处,1是usb转串口的路径,修改为上面查询到的,2是存放编译好的固件的位置。
strComDev = /dev/ttyUSB0
strImagePath = ../out/xr_system.img
修改完成后保存。
##4.开始下载
执行命令 ./phoenixMC
当看到 100%: Upgrade OK! 表明下载已经成功,可以按下开发板的复位键或者直接拔插一下开发板的USB数据线让开发板复位重新上电,即可运行我们的程序。
#6. 附上工程文件下载地址
gitee工程文件链接
#7. 参考文章
实现本工程除了参考官方历程,还参考了以下作者的代码,在此表示感谢!
【XR806开发板试用】SPI外设使用&&驱动OLED显示
【XR806开发板试用】实时时钟