文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

硬件通信:串口、I2C、SPI、I2S 开发例程

2024-11-30 15:54

关注

想了解更多关于开源的内容,请访问:

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

一、硬件通信

1、串口通信

(1)Uart函数接口

涉及串口相关的函数主要是初始化、发送/读取数据、去初始化函数整理如下:

函数

描述

依赖

IoTUartInit(unsigned int id, const IotUartAttribute *param)

初始化指定的UART端口id: 表示UART设备的端口号param:表示指向UART属性的指针

//base/iot_hardware/peripheral/interfaces/kits/iot_uart.h

IoTUartRead(unsigned int id, unsigned char *data, unsigned int dataLen)

从UART设备中读取指定长度的数据id: 表示UART设备的端口号data: 表示指向要读取数据的起始地址的指针dataLen: 表示要读取的字节数

//base/iot_hardware/peripheral/interfaces/kits/iot_uart.h

IoTUartWrite(unsigned int id, const unsigned char *data, unsigned int dataLen)

将指定长度的数据写入UART设备

//base/iot_hardware/peripheral/interfaces/kits/iot_uart.h

IoTUartDeinit(unsigned int id)

去初始化指定的UART端口

/base/iot_hardware/peripheral/interfaces/kits/iot_uart.h

另外,查看iot_uart.h文件可知,其只是对hi_uart.h中定义的函数进行了再一次封装,hi_uart.h中还定义了限时读取函数:


hi_s32 hi_uart_read_timeout(hi_uart_idx id, hi_u8 *data, hi_u32 len, hi_u32 timeout_ms);

串口主要参数有波特率、串口号、奇偶校验等使用一个IotUartAttribute结构体定义,iot_uart.h中具体定义如下:


typedef struct {

unsigned int baudRate;

IotUartIdxDataBit dataBits;

IotUartStopBit stopBits;

IotUartParity parity;

IotUartBlockState rxBlock;

IotUartBlockState txBlock;

unsigned char pad;
} IotUartAttribute;

(2)串口蓝牙案例

下面我们做一个简单的串口通信实验,将一串自定义数据通过Hi3861的UART1发送到蓝牙模块(或者其他开发板)。开发流程有以下几步:配置并开启串口、编写发送\读取任务逻辑、开启任务线程、编译运行测试。
开发准备:两块hi3861开发板或者hi3861开发板和带串口的设备(如HC05串口蓝牙模块)

#define BLUE_RX_1 1
#define BLUE_TX_0 0
int Bluetooth_Init()
{
// 初始化GPIO
IoTGpioInit(HI_IO_NAME_GPIO_0);
hi_io_set_func(BLUE_TX_0, HI_IO_FUNC_GPIO_0_UART1_TXD);
IoTGpioInit(HI_IO_NAME_GPIO_1);
hi_io_set_func(BLUE_RX_1, HI_IO_FUNC_GPIO_1_UART1_RXD);

// 配置UART 1参数
IotUartAttribute my_param; //={115200,8,1,HI_UART_PARITY_NONE,0,0};

my_param.baudRate=115200;

my_param.dataBits=8;

my_param.stopBits=1;

my_param.parity=HI_UART_PARITY_NONE;
return IoTUartInit(HI_UART_IDX_1, &my_param);
}
// 串口蓝牙数据交互
static void BluetoothTask(void *arg)
{
char send_data[] = "Hello OpenHarmony";
IoTUartWrite(HI_UART_IDX_1, (unsigned char*)send_data, strlen(send_data));

char get_data[8] = {0};
int data_len = 8;
while (1)
{
usleep(500000); // 0.5s
ret = IoTUartRead(HI_UART_IDX_1, get_data, data_len);
if (ret == 0)
printf("get_data = %s\n", get_data);
else
printf("get_data Falile\r\n");
}
}
#include 
#include
#include "ohos_init.h"
#include "cmsis_os2.h"

#include
#include "hi_io.h" // 定义了GPIO编号、描述GPIO功能
#include "hi_uart.h"
#include "iot_uart.h"

#define BLUE_RX_1 1
#define BLUE_TX_0 0

int Bluetooth_Init()
{
// 初始化GPIO
IoTGpioInit(HI_IO_NAME_GPIO_0);
hi_io_set_func(BLUE_TX_0, HI_IO_FUNC_GPIO_0_UART1_TXD);
IoTGpioInit(HI_IO_NAME_GPIO_1);
hi_io_set_func(BLUE_RX_1, HI_IO_FUNC_GPIO_1_UART1_RXD);

// 配置UART 1参数
IotUartAttribute my_param; //={115200,8,1,HI_UART_PARITY_NONE,0,0};

my_param.baudRate=115200;

my_param.dataBits=8;

my_param.stopBits=1;

my_param.parity=HI_UART_PARITY_NONE;
return IoTUartInit(HI_UART_IDX_1, &my_param);
}
//测试蓝牙
static void BluetoothTask(void *arg)
{
(void)arg;
sleep(2);
int ret = 1;
ret = Bluetooth_Init();
if (ret != 0)
{
printf("Uart1 init failed! \n");
return;
}
char send_data[] = "Hello OpenHarmony";
IoTUartWrite(HI_UART_IDX_1, (unsigned char*)send_data, strlen(send_data));

char get_data[8] = {0};
int data_len = 8;
while (1)
{
usleep(500000); // 0.5s
ret = IoTUartRead(HI_UART_IDX_1, get_data, data_len);
if (ret == 0)
printf("get_data = %s\n", get_data);
else
printf("get_data Falile\r\n");
}
}

static void BluetoothDemo(void)
{
osThreadAttr_t attr;
attr.name = "BluetoothTask";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 4096;
attr.priority = osPriorityNormal;
if (osThreadNew(BluetoothTask, NULL, &attr) == NULL)
{
printf("[BlueDemo] Falied to create BluetoothTask!\n");
}
}
APP_FEATURE_INIT(BluetoothDemo);
static_library("led_example") {
sources = [
# "led_example.c",
# "gpio_input_output.c",
# "gpio_adc.c",
# "gpio_pwm.c",
"uart_bluetooth.c",
]
include_dirs = [
"//utils/native/lite/include",
"//kernel/liteos_m/kal/cmsis",
"//base/iot_hardware/peripheral/interfaces/kits",
"//device/hisilicon/hispark_pegasus/sdk_liteos/include",
]
}

连接蓝牙模块(或者串口模块)RT、TX要交叉。我这里连接了HC05蓝牙模块,然后使用手机连接蓝牙,互相发送数据。测试效果如下:

(3)串口使用注意事项

2、I2C通信

(1)I2C函数接口

I2C是常用硬件接口,MPU6050、温湿度传感器等会使用到。I2C的原理可见​​Analog Dialogue I2C​​。I2C相关函数接口整理如下:

函数

描述

依赖

IoTI2cInit(unsigned int id, unsigned int baudrate)

以指定的波特率初始化I2C设备。id:I2C设备ID baudrate:指定的I2C波特率

//base/iot_hardware/peripheral/interfaces/kits/iot_i2c.h

IoTI2cWrite(unsigned int id, unsigned short deviceAddr, const unsigned char *data, unsigned int dataLen)

将数据写入I2C设备

//base/iot_hardware/peripheral/interfaces/kits/iot_i2c.h

IoTI2cRead(unsigned int id, unsigned short deviceAddr, unsigned char *data, unsigned int dataLen);

从I2C设备读取数据

//base/iot_hardware/peripheral/interfaces/kits/iot_i2c.h

IoTI2cSetBaudrate(unsigned int id, unsigned int baudrate)

设置I2C设备的波特率

//base/iot_hardware/peripheral/interfaces/kits/iot_i2c.h

上述IoTI2cRead、IoTI2cWrite实质是分别把hi_i2c_wirte()、hi_i2c_read()函数进行一层封装,实际建议直接使用hi_i2c_wirte()、hi_i2c_read() 【在hi_i2c.h文件中有定义编写程序,发送数据更灵活一些。
另外,在hi_i2c.h中定义了发送的数据类型,可以看到是一个结构,接收时可以不用指定send_buf、send_len两个变量,同理发送时可以不用指定另外两个变量。


typedef struct {
hi_u8* send_buf;
hi_u32 send_len;
hi_u8* receive_buf;
hi_u32 receive_len;
} hi_i2c_data;

(2)温湿度传感器案例

在本实验中我们将编写程序,获取环境温湿度,检测可燃气体,采集的数据通过串口输出,当温度高于 25 摄氏度时,实验板上的蜂鸣器鸣响。其中温湿度传感器为 AHT20,使用i2c 协议传输数据到 hi3861 核心板,可燃气体传感器输出模拟量,需要使用 ADC 功能采集数据;无源蜂鸣器使用 PWM 信号驱动。开发流程总结为:了解AHT20 数据手册、配置i2C接口、编写连接设备收发数据的任务逻辑、注册线程任务、运行调试。

需要注意的是,每个传感器已经通过底板连接到固定 GPIO,对应的连接关系整理如下:

蜂鸣器——PWM 控制声音的频率和音量
GPIO09: PWM0
MQ2 燃气传感器——ADC 读取模拟值
GPIO11: ADC5
AHT20 温湿度传感器——I2C 接口,设备地址 0x38
GPIO13: I2C0_SDA
GPIO14: I2C0_SCL

软件分为两个部分,第一部分是获取温湿度传感器 AHT20数据。新建如下三个文件:

applications\sample\wifi-iot\app\iothardware\aht20.h :声明相关函数。
applications\sample\wifi-iot\app\iothardware\aht20.c :初始化传感器,读取并处理数据。
applications\sample\wifi-iot\app\iothardware\environment.c :本实验任务在此文件开启线程。
#define AHT20_SCL 14
#define AHT20_SDA 13
#define AHT20_I2C_IDX 0 //--i2c0
#define AHT20_I2C_BAUDRATE 400*1000 //--i2c波特率400K
#define AHT20_ADDR 0x38
#define AHT20_READ ((0x38<<1)|0x1) //--SDA-读
#define AHT20_WRITE ((0x38<<1)|0x0) //--SDA-写
#define AHT20_INIT_CMD 0xBE //--初始化(校准)命令
#define AHT20_INIT_CMD_B1 0x08
#define AHT20_INIT_CMD_B2 0x00
#define AHT20_TRAG_CMD 0xAC //--触发测量
#define AHT20_TRAG_CMD_B1 0x33
#define AHT20_TRAG_CMD_B2 0
#define AHT20_RESET_CMD 0xBA //--软复位(不断电复位)
#define AHT20_STATUS 0x71 //--获取状态位
#define AHT20_WAIT_TIME 100 //复位、传感器测量数据等待时间 ms
//使能 i2c-0
void AHT20_I2C_Init(void)
{
IoTGpioInit(AHT20_SDA);
hi_io_set_func(AHT20_SDA,HI_IO_FUNC_GPIO_13_I2C0_SDA);
IoTGpioInit(AHT20_SCL);
hi_io_set_func(AHT20_SCL,HI_IO_FUNC_GPIO_14_I2C0_SCL);
hi_i2c_init(AHT20_I2C_IDX,AHT20_I2C_BAUDRATE);
}
// 读取数据
static uint32_t AHT20_Read(uint8_t *data, uint32_t dataLen)
{
hi_i2c_idx id = AHT20_I2C_IDX;
hi_i2c_data i2cData;
i2cData.receive_buf = data;
i2cData.receive_len = dataLen;
i2cData.send_buf = NULL;
i2cData.send_len = 0;
uint32_t result;
result = hi_i2c_read((hi_i2c_idx)id,AHT20_READ,&i2cData);
if(result != IOT_SUCCESS){
printf("AHT20_Read() Failed ,%0X\n",result);
return result; }
return IOT_SUCCESS ;
}
// 发送数据
static uint32_t AHT20_Write(uint8_t *data, uint32_t dataLen)
{
hi_i2c_idx id = AHT20_I2C_IDX;
hi_i2c_data i2cData;
i2cData.receive_buf = NULL;
i2cData.receive_len = 0;
i2cData.send_buf = data;
i2cData.send_len = dataLen;
uint32_t result;
result = hi_i2c_write((hi_i2c_idx)id,AHT20_WRITE,&i2cData);
if(result != IOT_SUCCESS){
printf("AHT20_Write() Failed ,%0X\n",result);
return result; }
return IOT_SUCCESS ;
}

当编写基本的数据发送读取函数后,可调用其发送指令,例如复位、获取传感器状态等。

//获取状态
static uint32_t AHT20_Status(void)
{
uint8_t statuscmd={AHT20_STATUS};
return AHT20_Read(&statuscmd,sizeof(statuscmd));
}
//软复位
static uint32_t AHT20_Reset(void)
{
uint8_t reset = {AHT20_RESET_CMD};
return AHT20_Write(&reset,sizeof(reset));
}
//校准
static uint32_t AHT20_Initcmd(void)
{
uint8_t initialcmd[] ={AHT20_INIT_CMD, AHT20_INIT_CMD_B1,AHT20_INIT_CMD_B2};
return AHT20_Write(&initialcmd,sizeof(initialcmd));
}
//触发测量
uint32_t AHT20_StartMeasure(void)
{
uint8_t startcmd[] ={AHT20_TRAG_CMD, AHT20_TRAG_CMD_B1,AHT20_TRAG_CMD_B2};
return AHT20_Write(&startcmd,sizeof(startcmd));
}
/ *程序功能:
1. 读取燃气传感器的ADC值;
2. 读取AHT20温湿度传感器的数值;
3. 温度、湿度上升(哈一口气)蜂鸣器叫几声.
基于hi3861_hdu开发 编译运行通过
*/
#include "aht20.h"
#define BEEP_PWM 0
#define BEEP_IO 9
#define MQ2_IO 11

static void EnviroTask(void *arg)
{
(void) arg;
unsigned int data;
float temp;
float humi;
while(1)
{
if(hi_adc_read(HI_ADC_CHANNEL_5,&data,HI_ADC_EQU_MODEL_1,HI_ADC_CUR_BAIS_DEFAULT, 0)==0)
{ printf("燃气MQ2 data:%d\n",data);}

AHT20_Calibrate();
AHT20_StartMeasure();
AHT20_GetMeasureResult(&temp, &humi);

printf(" 温度temp:%.3f ",temp);
printf(" 湿度humi:%.3f\n",humi);
if(temp>25) //温度大于25摄氏度,蜂鸣器叫
{
IoTPwmStart(BEEP_PWM,90,40000);
}
else{
IoTPwmStop(BEEP_PWM);
}
}
}

static void EnviroEntry(void)
{
IoTGpioInit(BEEP_IO);
hi_io_set_func(BEEP_IO,HI_IO_FUNC_GPIO_9_PWM0_OUT);
IoTPwmInit(BEEP_PWM);

IoTGpioInit(MQ2_IO);
hi_io_set_func(MQ2_IO,HI_IO_FUNC_GPIO_5_GPIO);

AHT20_I2C_Init();

osThreadAttr_t attr;
attr.name = "EnviroTask";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.priority = 24;
attr.stack_size = 4096;
if(osThreadNew(EnviroTask,NULL,&attr)==NULL)
{
printf("[EnviroEntry] Failed to create EnviroTask!\n ");
}
}
APP_FEATURE_INIT(EnviroEntry);
static_library("led_example") {
sources = [
# "led_example.c",
# "gpio_input_output.c",
# "gpio_adc.c",
# "gpio_pwm.c",
# "uart_bluetooth.c",
"aht20.c",
"environment.c",
]
include_dirs = [
"//utils/native/lite/include",
"//kernel/liteos_m/kal/cmsis",
"//base/iot_hardware/peripheral/interfaces/kits",
"//device/hisilicon/hispark_pegasus/sdk_liteos/include",
]
}

运行结果如下图:

可以用手触摸或者对着温湿度传感器哈气,可以看到数值在变化,燃气传感器会微微发热,也有数值,条件允许可以点一根蜡烛,然后熄灭它,刚熄灭后的的白烟可以让MQ2传感器的数值发生变化。至此该实验全部结束。

3、SPI通信

(1)SPI函数接口

SPI相关理论可以参考Analoge Dialogue SPI。hi3861支持2路SPI。这里给出相关函数,具体实践可根据需求调用API即可。i2S相关定义在文件src\device\hisilicon\hispark_pegasus\sdk_liteos\include\hi_spi.h中。

// 初始化spi
hi_u32 hi_spi_init(hi_spi_idx spi_id, hi_spi_cfg_init_param init_param, const hi_spi_cfg_basic_info *param);
// 中断模式配置
hi_u32 hi_spi_set_irq_mode(hi_spi_idx id, hi_bool irq_en);
// dma模式配置
hi_u32 hi_spi_set_dma_mode(hi_spi_idx id, hi_bool dma_en);
// 从机写
hi_u32 hi_spi_slave_write(hi_spi_idx spi_id, hi_pvoid write_data, hi_u32 byte_len, hi_u32 time_out_ms);
// 从机度
hi_u32 hi_spi_slave_read(hi_spi_idx spi_id, hi_pvoid read_data, hi_u32 byte_len, hi_u32 time_out_ms);
// 主机写
hi_u32 hi_spi_host_write(hi_spi_idx spi_id, hi_pvoid write_data, hi_u32 byte_len);
// 主机读
hi_u32 hi_spi_host_read(hi_spi_idx spi_id, hi_pvoid read_data, hi_u32 byte_len);

4、I2S通信

(1)I2S函数接口

I2S相关理论可以参考Analoge Dialogue I2S。hi3861支持一路I2S。这里给出相关函数,具体实践可根据需求调用API即可。i2S相关定义在文件src\device\hisilicon\hispark_pegasus\sdk_liteos\include\hi_i2s.h中。


typedef enum {
HI_I2S_SAMPLE_RATE_8K = 8,
HI_I2S_SAMPLE_RATE_16K = 16,
HI_I2S_SAMPLE_RATE_32K = 32,
HI_I2S_SAMPLE_RATE_48K = 48,
} hi_i2s_sample_rate;


typedef enum {
HI_I2S_RESOLUTION_16BIT = 16,
HI_I2S_RESOLUTION_24BIT = 24,
} hi_i2s_resolution;


typedef struct {
hi_i2s_sample_rate sample_rate;
hi_i2s_resolution resolution;
} hi_i2s_attribute;
hi_u32 hi_i2s_init(const hi_i2s_attribute *i2s_attribute);
hi_u32 hi_i2s_read(hi_u8 *rd_data, hi_u32 rd_len, hi_u32 time_out_ms);
hi_u32 hi_i2s_write(hi_u8 *wr_data, hi_u32 wr_len, hi_u32 time_out_ms);

文章相关附件可以点击下面的原文链接前往下载

 https://ost.51cto.com/resource/2684。

想了解更多关于开源的内容,请访问:

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

来源:51CTO 开源基础软件社区内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯