怎么从STM32将代码移植到海思开发板Hi3861


前言

目前正在打大学生嵌入式大赛,本人负责的部分是对Hi3861开发板进行开发,因为以前玩的更多的是STM32,所以产生的idea会先在STM32上实现再试着转移到Hi3861开发板上,这其实符合大部分日嵌入式开发玩家的流程开发。


提示:下面案例可供参考

一、Hi3861是什么?

Hi3861其实并不是华为独自研发的,Hi3861是润和开发的一款开发板,华为海思和他们是一个合作的关系。

Hi3861LV100是一款高度集成的2.4GHz WiFi SoC芯片,集成IEEE 802.11b/g/n基带和RF电路,RF电路包括功率放大器PA、低噪声放大器LNA、RF balun、天线开关以及电源管理等模块;支持20MHz标准带宽和5MHz/10MHz窄带宽,提供最大72.2Mbit/s物理层速率。

Hi3861LV100WiFi基带支持正交频分复用(OFDM)技术,并向下兼容直接序列扩频(DSSS)和补码键控(CCK)技术,支持IEEE 802.11b/g/n协议的各种数据速率。

Hi3861LV100芯片集成高性能32bit微处理器、硬件安全引擎以及丰富的外设接口,外设接口包括SPI、UART、I2C、PWM、GPIO和多路ADC,同时支持高速SDIO2.0
Slave接口,最高时钟可达50MHz;芯片内置SRAM和Flash,可独立运行,并支持、在Flash上运行程序。

Hi3861LV100支持Huawei LiteOS和第三方组件,并配套提供开放、易用的开发和调试运行环境。

Hi3861LV100芯片适应于智能家电、智能门锁、低功耗Camera、BUTTON等物联网低功耗智能产品领域。

二、使用步骤

1.写一个STM32程序

首先,一个STM32的程序怎么转移过去一个其他的板子呢?(本文为Hi3861)

  1. 需要看两个板子对应的引脚,本文转移的是一个ADC读取传感器电压变化值的代码,那么首先需要看的就是Hi3861哪些引脚支持ADC功能复用,也就是能不能用这个引脚读取电压值。
  2. 其次需要看第二个板子的要怎么设置,比如STM32写代码通常需要导包(相应的系统包)、设置魔法棒(path路径等),两者对比的设置如下两图所示。

请添加图片描述

请添加图片描述
3. 在导入对应的代码包(如adc.h此类),建议Hi3861直接用一个官方给的Hello world例程开发,这样就省去了很多和STM32一样的导包麻烦啦
4. 导包完成就是配置Hi3861支持的库了(专业名称BSP(板级支持包))。这一步很重要!这一步很重要!这一步很重要!如果你要使用Hi3861的相应功能但是你没有勾选支持的BSP的话,代码写对了也没用!比如要写一个OLED的显示功能,那么必须勾选IIC的support。

2.如何转移到Hi3861

弄完了基础的配置之后就是如何转移代码的问题了。我直接贴上一部分的代码分析,有需要的自行去文章末尾下载工程文件
STM32代码如下:

int main(void)
 {	 
    u16 adcx;
	float temp;
	u8 lcd_id[12];			//存放LCD ID字符串
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 	//串口初始化为115200
 	LED_Init();			     //LED端口初始化
   Adc_Init();		  		//ADC初始化
	LCD_Init();
	sprintf((char*)lcd_id,"LCD ID:%04X",lcddev.id);//将LCD ID打印到lcd_id数组。
   POINT_COLOR=RED;//设置字体为红色 
   LCD_ShowString(60,50,200,16,16,"Elite STM32");	
	LCD_ShowString(60,70,200,16,16,"ADC TEST");	
	LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
	LCD_ShowString(60,110,200,16,16,"2015/1/14");	
	//显示提示信息
	POINT_COLOR=BLUE;//设置字体为蓝色
	LCD_ShowString(60,130,200,16,16,"ADC_CH0_VAL:");	      
	LCD_ShowString(60,150,200,16,16,"ADC_CH0_VOL:0.000V");    
  	while(1) 
	{		
      adcx=Get_Adc_Average(ADC_Channel_1,10);
		LCD_ShowxNum(156,130,adcx,4,16,0);//显示ADC的值
		temp=(float)adcx*(3.3/4096);
		adcx=temp;
		LCD_ShowxNum(156,150,adcx,1,16,0);//显示电压值
		temp-=adcx;
		temp*=1000;
		LCD_ShowxNum(172,150,temp,3,16,0X80);
		LED0=!LED0;
		delay_ms(250);
		LED0=!LED0;				   		 
		delay_ms(1000);	
	} 
}
//此处直接用的是正点原子的官方ADC例程,主要是为了转移的思想,转移什么代码不重要

这个代码主要的步骤就是初始化需要采集电压引脚,配置ADC,拿到模拟量之后用函数转移为数字量(ADC过程)显示到LCD上。代码的思想很简单

Hi3861代码如下:

#include <hi_early_debug.h>
#include <hi_task.h>
#include <stdio.h>
#include <hi_adc.h>
#include <hi_gpio.h>
#include <hi_io.h>
#include <hi_stdlib.h>
#include <hi_i2c.h>
#include <ssd1306_oled.h>

#define WATER_SENSOR_TASK_SIZE  ( 1024*2 )
#define WATER_SENSOR_TASK_PRIO  ( 28 )
#define ADC_LENGTH         ( 20 )
#define VLT_MIN (100)

hi_u16 g_water_sensor_adc_buf[ADC_LENGTH];

extern hi_u32 oled_init(hi_void);
extern hi_void oled_show_str(hi_u8 x, hi_u8 y, hi_u8 *chr, hi_u8 char_size);
/*
	@berf gpio_config:i2c 0 Pin reuse is I2C mode
*/
hi_void gpio_config() {
    hi_io_set_func(HI_IO_NAME_GPIO_13, HI_IO_FUNC_GPIO_13_I2C0_SDA);
    hi_io_set_func(HI_IO_NAME_GPIO_14, HI_IO_FUNC_GPIO_14_I2C0_SCL);
}
/*
	@berf oled Screen display initialization
	@param hi_void
*/
hi_void water_sensor_display(hi_void)
{
    hi_i2c_init(HI_I2C_IDX_0, HI_I2C_IDX_BAUDRATE); /* baudrate: 400kbps */
    hi_i2c_set_baudrate(HI_I2C_IDX_0, HI_I2C_IDX_BAUDRATE);
    oled_init();

    oled_fill_screen(OLED_CLEAN_SCREEN);//clear screen  
}
/*
	gpio init Pin initialization
*/
hi_void water_sensor_gpio_init(hi_void)
{
    hi_io_set_func(HI_IO_NAME_GPIO_7, HI_IO_FUNC_GPIO_7_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_7, HI_GPIO_DIR_IN);
}

hi_void *water_sensor(hi_void *param)
{
    hi_u32 ret;
    hi_u16 data;
    float voltage;
    hi_float vlt_max = 0;
    hi_float vlt_min = VLT_MIN;
    hi_u32 i;
    
    while (1) {
        memset_s(g_water_sensor_adc_buf, sizeof(g_water_sensor_adc_buf), 0x0, sizeof(g_water_sensor_adc_buf));
        for (i = 0; i < ADC_LENGTH; i++) {
            vlt_max =0;
            ret = hi_adc_read(HI_ADC_CHANNEL_3, &data, HI_ADC_EQU_MODEL_4, HI_ADC_CUR_BAIS_DEFAULT, 0xF0); //CHANNAL 3 GPIO 7
            if (ret != HI_ERR_SUCCESS) {
                printf("ADC Read Fail\n");
                return HI_NULL;
            }
            printf("adc original data %d \n", data);
            voltage = (float)data * 1.8 * 4 / 4096.0;  /* vlt * 1.8 * 4 / 4096.0 is to convert codeword to voltage */
            vlt_max = (voltage > vlt_max) ? voltage : vlt_max;
            vlt_min = (voltage < vlt_min) ? voltage : vlt_min;
            printf( "vlt_min:%.3f, vlt_max:%.3f \n", vlt_min, vlt_max );       
            if (vlt_max > 1) {
                oled_show_str(0, 4, "is Rainning", 16);/*The test results will be displayed on the screen, if moisture is detected, it will display "it's raining"*/
            } else if (vlt_max < 1) {
                oled_show_str(0, 4, "a sunny day", 16);/*The test results will be displayed on the screen, if no moisture is detected, "sunny" will be displayed”*/
            }
        }
        hi_sleep(100);
    }
}
/*
	@berf Create simulated moisture sensor task
	@param hi_void
	@return Task created successfully ret = HI_ERR_SUCCESS,Failed ret = 0x800xxxx 
*/
hi_u32 water_sensor_task(hi_void)
{
    hi_u32 ret;
    hi_task_attr attr ={0};
    hi_u32 water_sensor_id;
    gpio_config();
    /*adc gpio init*/
    water_sensor_gpio_init();
    /*oled display*/
    water_sensor_display();
	/*attr Configuration of structural parameters*/
    attr.stack_size = WATER_SENSOR_TASK_SIZE;//Task stack memory
    attr.task_prio = WATER_SENSOR_TASK_PRIO;//The task priority ranges from 0 to 31. Tasks 0 to 10 should not be used. The SDK has been used. The higher the value, the lower the priority
    attr.task_name = (hi_char*)"water_sensor_task";//task name
	/*create task*/
    ret = hi_task_create(&water_sensor_id, &attr, water_sensor, HI_NULL);
    if (ret != HI_ERR_SUCCESS) {
        printf("Failed to create water_sensor_task\r\n");
    }
    return HI_ERR_SUCCESS;
}

这个代码是拿官方写的一个adc例程(此处我怕贴我自己写的不好讲清楚)

可以看到Hi3861和STM32最大的不同点就是Hi3861采用的是多线程执行方式,STM32采用的是顺序执行方式。所以正规的开发Hi3861的流程是:先创建一个线程任务,即create task,然后将需要实现的放入到线程任务跳转的功能函数中。

例:/create task/
ret = hi_task_create(&water_sensor_id, &attr, water_sensor, HI_NULL);
其中water_sensor是功能函数。
没了解过多线程单片机系统开发的先不要纠结为什么这么写,先学会用!照猫画虎
钢铁侠说过:有时候学会走之前要先试着跑起来!(是这么说的嘛我不记得了,大概大概


Hi3861中的hi_adc_read函数,这些就需要去看API文档和相关硬件设计的文档了。这里附上一些我接触过了引脚复用为ADC的
1.ret = hi_adc_read(HI_ADC_CHANNEL_3, &data, HI_ADC_EQU_MODEL_4, HI_ADC_CUR_BAIS_DEFAULT, 0xF0); //CHANNAL 3 GPIO 7

2.ret = hi_adc_read(HI_ADC_CHANNEL_2, &data, HI_ADC_EQU_MODEL_4, HI_ADC_CUR_BAIS_DEFAULT, 0); //CHANNAL 2 GPIO 5

3.ret = hi_adc_read(HI_ADC_CHANNEL_5, &data, HI_ADC_EQU_MODEL_4, HI_ADC_CUR_BAIS_DEFAULT, 0xF0); //CHANNAL 5 GPIO 11
里面的参数设计就需要看API文档了,我贴心 的给大家准备好了
ADC函数

总结

本文介绍了怎么把一个STM32的程序转移到Hi3861上,其实这个思想适用于大多数的转移开发板代码。

把一些工程发上来给大家,仅供参考~

STM32F103火焰传感器ADC实验例程

Hi3861实现火焰传感器例程代码

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白面师傅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值