【沁恒微CH32V307评估板试用体验】开箱及运行HarmonyOS并点双灯 - RISC-V MCU技术社区 - 电子技术william hill官网 - 广受欢迎的专业电子william hill官网 - 威廉希尔官方网站
分享 收藏 返回

[文章]

【沁恒微CH32V307评估板试用体验】开箱及运行HarmonyOS并点双灯

[i=s] 本帖最后由 HonestQiao 于 2022-5-19 12:57 编辑 [/i]

这次有幸收到了CH32V307评估板,拿到第一时间,开箱,再点灯。

一、开箱:

沁恒的板子,包装一如既往的比较简洁,和小弟103在一起:

1.与103对比.jpg

2.与103对比.jpg

两者的说明书,完全一样,除了名字:

3.说明资料.jpg

再来看一看正面:

4.正面.jpg

和103一样,自带WCH-LINK,对于开发者非常方便,接上就可以调试了。

板子上,带有可以独立控制的两个LED,两个按钮(1个RESET,1个USER可控制的),两个type-C口,后有一个有线网口。

另外,接口是Arduino兼容的,可以把Arduino扩展板直接接上使用。

3.5和arduino对比.jpeg

然后,再看看反面:

5.反面.jpg

最后再来一张冲击照:

6.近照.jpg

看完板子,就是点灯。

二、官方GPIO点灯实例

我们先来看看沁恒提供的例子,真的是非常的丰富,方方面面的全都有了,对学习者非常的友好。

9.代码.png

在上面的例子中,我是一眼就看到了HarmonyOS,下面要做的,就是跑HarmonyOS,并结合GPIO实例,在HarmonyOS点灯。

首先,要下载专用的开发工具 MounRiver Studio,下载地址为:

MounRiver Studio

选择 集成开发环境 即可。熟悉Eclipse的同学,可以选择社区版。

下载后,完成安装,就可以到示例目录中,项目名.wvproj,就能直接打开例子项目了。

MounRiver Studio的使用,请大家查看官方的资料《CH32V30x评估板说明书.pdf》,这里就不多说了。

因为要点灯,所以我们先打开GPIO/GPIO_Toggle项目,具体如下:

3.GPIO实例.png

在上述代码中,GPIO_Toggle_INIT进行初始化,GPIO_WriteBit负责设置对应GPIO端口的输出。

要正确点灯,我们需要从原理图上,先了解LED的线路。

在CH32V307评估板上,通过原理图,我们可以了解到,可以使用的Pin如下:

Pin.png

从其中可以看到,CH32V307的引脚,是分组为PA、PB、PC、PD的。

看板子正面,会更清晰:

4.正面.jpg

板子上的两个LED 的威廉希尔官方网站 如下:

LED.png

这两个LED是独立的,可以通过跳线,连接到任意的GPIO端口,进行控制。

方便起见,我把LED1连接到了PA0,LED2连接到了PA1,具体如下:

7.1.png
(感谢lingxin-yuhe指出原图错误,已修正)

从GPIO/GPIO_Toggle的GPIO_Toggle_INIT中,我们看到,对PA0进行了初始化,驱动连接到PA0的LED,那后面,我们就会对PA0、PA1初始化,从而驱动两个LED。

把LED1连接到PA0以后,编译源码,然后下载,LED1就会快速闪动了。

MounRiver Studio的按钮导航栏如下:

2.按钮.png

其中红框框起来的部分:

绿色单下箭头:表示编译

绿色双下箭头:重新编译

白色单下箭头:表示下载编译后的HEX到开发板

绿色虫子:表示debug调试,可以断点运行

下载前,应该先点下载旁边的小箭头,打开下载配置界面:

1.解除代码保护.png

  • 放大镜图标:查询代码保护状态
  • 加锁图标:锁定,不可下载
  • 解锁图标:解锁,可以下载

要下载代码,应确保点击放大镜图标,查看已经处于解锁图标。

三、HarmonyOS点双灯:

直接点击HarmonyOS/LiteOS_m/LiteOS_m.wvproj,就可以打开HarmonyOS项目,并参考GPIO/GPIO_Toggle进行修改,代码如下:

4.GPIO初始化.png

5.初始化2.png

上述代码中,对PA0和PA1进行了初始化。

6.main.png

上述为main部分,添加了GPIO_Toggle_INIT()调用。

7.任务.png

在原有的两个task部分,分别切换PA0、PA1的状态,从而控制LED1、LED2的亮灭。

实际的连线如下:

7.接线.jpg

最终的代码如下:

#include "los_tick.h"

#include "los_task.h"
#include "los_config.h"
#include "los_interrupt.h"
#include "los_debug.h"
#include "los_compiler.h"

/* Global define */

/* Global Variable */
attribute((aligned (8))) UINT8 g_memStart[LOSCFG_SYS_HEAP_SIZE];
UINT32 g_VlaueSp=0;

// LED状态
u8 led_status = 0;
u8 led_status2 = 0;

/*********************************************************************

  • @fn GPIO_Toggle_INIT

  • [url=home.php?mod=space&uid=2666770]@Brief[/url] 初始化 GPIOA.0、GPIOA.1

  • [url=home.php?mod=space&uid=1141835]@Return[/url] none
    */
    void GPIO_Toggle_INIT(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    GPIO_InitTypeDef GPIO_InitStructure2 = {0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure2.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure2.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure2);
    }

/*********************************************************************

  • @fn taskSampleEntry2

  • @brief taskSampleEntry2 program.

  • @return none
    */
    VOID taskSampleEntry2(VOID)
    {
    while(1) {
    LOS_TaskDelay(2000);
    printf("taskSampleEntry2 running,task2 SP:xn",__get_SP());
    GPIO_WriteBit(GPIOA, GPIO_Pin_1, (led_status2 == 0) ? (led_status2 = Bit_SET) : (led_status2 = Bit_RESET));
    }
    }

/*********************************************************************

  • @fn taskSampleEntry1

  • @brief taskSampleEntry1 program.

  • @return none
    */
    VOID taskSampleEntry1(VOID)
    {
    while(1) {
    LOS_TaskDelay(1000);
    printf("taskSampleEntry1 running,task1 SP:xn",__get_SP());
    GPIO_WriteBit(GPIOA, GPIO_Pin_0, (led_status == 0) ? (led_status = Bit_SET) : (led_status = Bit_RESET));
    }

}

/*********************************************************************

  • @fn EXTI0_INT_INIT

  • @brief Initializes EXTI0 collection.

  • @return none
    */
    void EXTI0_INT_INIT(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure={0};
    GPIO_InitTypeDef GPIO_InitStructure2={0};
    EXTI_InitTypeDef EXTI_InitStructure={0};
    NVIC_InitTypeDef NVIC_InitStructure={0};

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA,ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure2.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure2);

/* GPIOA ----> EXTI_Line0 */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
EXTI_InitStructure.EXTI_Line=EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

/*********************************************************************

  • @fn taskSample

  • @brief taskSample program.

  • @return none
    /
    UINT32 taskSample(VOID)
    {
    UINT32 uwRet;
    UINT32 taskID1,taskID2;
    TSK_INIT_PARAM_S stTask={0};
    stTask.pfnTaskEntry = (TSK_ENTRY_FUNC)taskSampleEntry1;
    stTask.uwStackSize = 0X500;
    stTask.pcName = "taskSampleEntry1";
    stTask.usTaskPrio = 6;/
    高优先级 */
    uwRet = LOS_TaskCreate(&taskID1, &stTask);
    if (uwRet != LOS_OK) {
    printf("create task1 failedn");
    }

    stTask.pfnTaskEntry = (TSK_ENTRY_FUNC)taskSampleEntry2;
    stTask.uwStackSize = 0X500;
    stTask.pcName = "taskSampleEntry2";
    stTask.usTaskPrio = 7;/* 低优先级 */
    uwRet = LOS_TaskCreate(&taskID2, &stTask);
    if (uwRet != LOS_OK) {
    printf("create task2 failedn");
    }

    EXTI0_INT_INIT();
    return LOS_OK;
    }

/*********************************************************************

  • @fn main

  • @brief Main program.

  • @return none
    */
    LITE_OS_SEC_TEXT_INIT int main(void)
    {
    unsigned int ret;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    Delay_Init();
    USART_Printf_Init(115200);
    printf("SystemClk:%drn",SystemCoreClock);
    GPIO_Toggle_INIT();

    ret = LOS_KernelInit();
    taskSample();
    if (ret == LOS_OK)
    {
    LOS_Start();
    }

    while (1) {
    __asm volatile("nop");
    }

}

/*********************************************************************

  • @fn EXTI0_IRQHandler

  • @brief This function handles EXTI0 Handler.

  • @return none
    /
    void EXTI0_IRQHandler(void) attribute((interrupt("WCH-Interrupt-fast")));
    void EXTI0_IRQHandler(void)
    {
    /
    中断栈使用的是原来调用main设置的值,将中断栈和线程栈分开,这样线程跳中断,中断函数如果嵌套深度较大,不至于

    • 线程栈被压满溢出,但是采用当前方式,线程进中断时,编译器保存到的16个caller寄存器任然压入线程栈,如果需要希

    • 望caller寄存器压入中断栈,则中断函数的入口和出口需要使用汇编,中间调用用户中断处理函数即可,详见los_exc.S

    • 中的ipq_entry例子

    • */
      GET_INT_SP();
      HalIntEnter();
      if(EXTI_GetITStatus(EXTI_Line0)!=RESET)
      {
      g_VlaueSp= __get_SP();
      printf("Run at EXTI:");
      printf("interruption sp:xrn",g_VlaueSp);
      HalDisplayTaskInfo();
      EXTI_ClearITPendingBit(EXTI_Line0); /* Clear Flag */
      }
      HalIntExit();
      FREE_INT_SP();
      }

编译下载后,两个LED,就会分别以自己的周期,进行亮灭了,如视频中所示。

回帖(6)

华仔stm32

2022-5-19 06:45:15
宣传一个鸿蒙系统,值得大家共同学习!

lingxin-yuhe

2022-5-19 10:03:55
ELED是网口上的路灯和黄灯,有一张图是不是有点问题。我开始也是有点迷糊,他俩就差一个字母。LED1和ELED1。实际的连接图是对的。
2

挽你何用

2023-3-13 09:23:34
厉害了,点个赞

洒下墨色

2023-3-15 17:33:17

更多回帖

×
发帖