在学OpenHarmonyos的SPI遇到的问题和总结以及Hi 3861读取W25Q64存储器的例程代码

博主分享HarmonyOS开发板学习案例。下载的源码默认未开启SPI,编译报错,需在文件中开启。介绍了SPI相关函数所在头文件及不同工作模式下的读写函数。还给出SPI初始化、读取W25Q64的代码部分,提醒修改BUILD.gn文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近学了stm32,转到学harmonyos开发板,网上关于H3861的资料也很少,分享一下自己学习的案例。

首先,我下载的源码是默认没有开启SPI的,编译的时候会报错,类似于这样的错误,

要使用SPI功能的话还需要在这个文件当中开启SPI的功能,

如果要开启其他的功能也是类似的方法,在这个文件随便哪个地方输入这行代码

CONFIG_SPI_SUPPORT =y

要开启其他的功能就把中间的SPI更换一下就好。

和SPI相关的函数

和SPI相关的函数都在hi_spi.h这个头文件里面,调用的时候参数类型要对应上就可以正常使用,hi_spi_slave_write()和hi_spi_slave_read()是在SPI初始化时候作为从机时的向主机写入和读取数据的函数,我这里是做主机使用,所以不涉及这两个函数,hi_spi_host_write()和hi_spi_host_read()这两个函数是作为主机,且为半双工时候的向从机写入和读取数据的函数,还有hi_spi_host_writeread(),作为主机且工作于全双工的读写数据的函数。当让还有最熟悉的hi_spi_init(),hi_spi_deinit()初始化和去初始化函数,其余的函数可以慢慢的去研究一下,不过单纯的使用SPI进行数据传输,这些函数完全够了。

代码部分

首先是SPI初始化部分,我尽量每行都给注释,少些废话。

void W25Q64_Init(void)
{
     hi_u32 ret;
    int i = 1;
    hi_spi_idx id = HI_SPI_ID_0;//我连接的是SPI0,具体看接线图
    hi_spi_deinit(id);//先去初始化
    hi_spi_cfg_basic_info spi_cfg_basic_info;定义一个包含spi初始化的参数信息的结构体
    spi_cfg_basic_info.cpha = 1;
    spi_cfg_basic_info.cpol = 1;//这两行把spi设置为工作在模式1
    spi_cfg_basic_info.data_width = HI_SPI_CFG_DATA_WIDTH_E_8BIT;//传输数据的宽度
    spi_cfg_basic_info.endian = 0;//首先发送或接收的是最高有效位
    spi_cfg_basic_info.fram_mode = 0;//传输途中的时钟极性
    spi_cfg_basic_info.freq = 9 * 800 * 1000;//频率
    hi_spi_cfg_init_param spi_init_param = {0};//这个是配置主机还是从机的结构体
    spi_init_param.is_slave = 0;//0为主机,1为从机
    ret = hi_spi_init(id, spi_init_param, &spi_cfg_basic_info); // 初始化
    if (ret != HI_ERR_SUCCESS) {
        printf("SPI init fail! %x ", ret);
    }//这个是打印到串口看有没有初始化成功的
    hi_io_set_func(HI_IO_NAME_GPIO_10,HI_IO_FUNC_GPIO_10_SPI0_CK);//设置gpio_10为clk模式
    hi_io_set_func(HI_IO_NAME_GPIO_11,HI_IO_FUNC_GPIO_11_SPI0_RXD);//设置gpio_11为MISO模式
    hi_io_set_func(HI_IO_NAME_GPIO_9,HI_IO_FUNC_GPIO_9_SPI0_TXD);//设置gpio_10为MOSI模式
 
    hi_io_set_func(HI_IO_NAME_GPIO_12,HI_IO_FUNC_GPIO_12_GPIO);
    hi_gpio_set_dir(HI_IO_NAME_GPIO_12,HI_GPIO_DIR_OUT);
    hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,HI_GPIO_VALUE1);
    hi_io_set_driver_strength(HI_IO_NAME_GPIO_12, HI_IO_DRIVER_STRENGTH_2);//这四行是设置gpio_12为NSS模式
}

然后是读取W25Q64

void W25Q64_ReadID(void)
{
    int ret=0;
    unsigned char resultdata;
    unsigned char writebuff[1] = {W25Q64_JEDEC_ID|test_num};
    unsigned char readbuff[4];
    hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,HI_GPIO_VALUE0);;  // 使能SPI传输
    ret = memset_s(readbuff, 4, 0x00, 4);//这个是创建一个缓冲区,长度为4,全部用0填充
    if (ret != EOK) {
        printf("memcpy_s failed, err = %d\n", ret);
    }
    ret = hi_spi_host_writeread(id, &writebuff, readbuff, 4);//全双工传输
    if (ret != HI_ERR_SUCCESS) {
        printf("spi read[%02X] fail! %x ", readbuff[0], ret);
    }
    printf("readresult:[%02X][%02X][%02X]",readbuff[1],readbuff[2],readbuff[3]);
    hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,HI_GPIO_VALUE1);;  // 禁止SPI传输
}

最后放一个整体的代码,还有一个BUILD.gn文件记得去做一些修改

#include "ohos_init.h"
#include <stdio.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "W25Q64_spi.h"
#include <hi_spi.h>

osThreadId_t Task1_ID = 0; //  任务1 ID
#define TASK_STACK_SIZE 1024
#define TASK_DELAY_TIME 5 // s


void GyroTask(void)
{
    W25Q64_Init();
    W25Q64_ReadID();
    
}

static void GyroControlTask(void)
{
    osThreadAttr_t attr;

    attr.name = "GyroCntrolDemo";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 1024 * 5; // 堆栈大小为1024 stack size 1024 * 5
    attr.priority = 25; // 优先级25
    if (osThreadNew((osThreadFunc_t)GyroTask, NULL, &attr) == NULL) {
        printf("[GyroExample] Failed to create GyroTask!\n");
    }
}

APP_FEATURE_INIT(GyroControlTask);
#include <stdio.h>
#include <hi_io.h>
#include <hi_early_debug.h>
#include <hi_task.h>
#include <hi_types_base.h>
#include <hi_spi.h>
#include <hi_time.h>
#include <../platform/drivers/spi/spi.h>
#include <hi_gpio.h>
#include "hi_io.h"

#define W25Q64_JEDEC_ID 0x1F
#define W25Q64_DUMMY_BYTE 0xFF
#define test_num 0x80

void W25Q64_Init(void)
{
     hi_u32 ret;
    int i = 1;
    hi_spi_idx id = HI_SPI_ID_0;
    hi_spi_deinit(id); /* if wake_up from deep sleep, should deinit first */
    hi_spi_cfg_basic_info spi_cfg_basic_info;
    spi_cfg_basic_info.cpha = 1;
    spi_cfg_basic_info.cpol = 1;
    spi_cfg_basic_info.data_width = HI_SPI_CFG_DATA_WIDTH_E_8BIT;
    spi_cfg_basic_info.endian = 0;
    spi_cfg_basic_info.fram_mode = 0;
    spi_cfg_basic_info.freq = 9 * 800 * 1000;
    hi_spi_cfg_init_param spi_init_param = {0};
    spi_init_param.is_slave = 0;
    ret = hi_spi_init(id, spi_init_param, &spi_cfg_basic_info); // 基本参数配置
    if (ret != HI_ERR_SUCCESS) {
        printf("SPI init fail! %x ", ret);
    }
    hi_io_set_func(HI_IO_NAME_GPIO_10,HI_IO_FUNC_GPIO_10_SPI0_CK);
    hi_io_set_func(HI_IO_NAME_GPIO_11,HI_IO_FUNC_GPIO_11_SPI0_RXD);
    hi_io_set_func(HI_IO_NAME_GPIO_9,HI_IO_FUNC_GPIO_9_SPI0_TXD);
   // IoSetFunc(IOT_IO_NAME_GPIO_11, IOT_IO_FUNC_GPIO_11_SPI0_RXD); // SPI MISO 数据从从发到主
   // IoSetFunc(IOT_IO_NAME_GPIO_9, IOT_IO_FUNC_GPIO_9_SPI0_TXD); // SPI MOSI 数据从主发到从
    hi_io_set_func(HI_IO_NAME_GPIO_12,HI_IO_FUNC_GPIO_12_GPIO);
    hi_gpio_set_dir(HI_IO_NAME_GPIO_12,HI_GPIO_DIR_OUT);
    hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,HI_GPIO_VALUE1);
   /*  IoSetFunc(IOT_IO_NAME_GPIO_12, IOT_IO_FUNC_GPIO_12_GPIO); // GYROcs片段
    IoTGpioSetDir(IOT_IO_NAME_GPIO_12, IOT_GPIO_DIR_OUT);
    IoTGpioSetOutputVal(IOT_IO_NAME_GPIO_12, IOT_GPIO_VALUE1); */
    hi_io_set_driver_strength(HI_IO_NAME_GPIO_12, HI_IO_DRIVER_STRENGTH_2);
}



void W25Q64_ReadID(hi_spi_idx id, unsigned char addrdata, unsigned char writedata, unsigned int writelen)
{
    int ret=0;
    unsigned char resultdata;
    unsigned char writebuff[1] = {W25Q64_JEDEC_ID|test_num};
    unsigned char readbuff[4];
    hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,HI_GPIO_VALUE0);;  // 使能SPI传输
    ret = memset_s(readbuff, 4, 0x00, 4);
    if (ret != EOK) {
        printf("memcpy_s failed, err = %d\n", ret);
    }
    ret = hi_spi_host_writeread(id, &writebuff, readbuff, 4);
    if (ret != HI_ERR_SUCCESS) {
        printf("spi read[%02X] fail! %x ", readbuff[0], ret);
    }
    //resultdata = readbuff[1];
    printf("readresult:[%02X][%02X][%02X]",readbuff[1],readbuff[2],readbuff[3]);
    
    hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,HI_GPIO_VALUE1);;  // 禁止SPI传输
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值