收藏官网首页
查看: 4148|回复: 0

[经验分享] 将机智云固件移植到risc-v平台以CH32V203C8T6为例

106

主题

107

帖子

7264

积分

论坛元老

Rank: 8Rank: 8

积分
7264
跳转到指定楼层
楼主
 楼主| 发表于 2023-8-15 21:58:57 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
免费使用STM32、APP自动代码生成工具
    虽然rsic-v起步较晚,但是目前rsic-v的生态正在迅速发展,各大厂商为其提供工具和开发环境,国产的risc-v芯片也不断涌现。对比arm,risc-v的主要优势在于指令集授权费用低,相比arm可以节省大量成本。而且risc-v是开源的,更具创造性。

接下来,简介一下使用的芯片。使用的是南京沁恒开发的青稞risc-v CH32V203C8T6 这是一款是基于32位RISC-V内核设计的工业级增强型低功耗通用微控制器,最高支持144MHz系统主频,低功耗,运行功耗低至45uA/MHz。

从系统框图可以看出,跟STM32f103还是很类似的,外设也很丰富,可以支持我们开发各种设备。
接下来,我们来移植机智云的协议,机智云已经为我们提供了通用平台的代码,我们只需要完成串口,定时器的驱动,剩下的对于事件,数据的处理无需我们关注,这大大减少了我们需要编写的代码。

因为risc-v内核不同于arm keil开发已经不是很适用了,因此这里使用的是risc-v的集成开发环境MounRiver Studio。
首先,我们创建一个新的项目,这里还是很方便的,选择芯片型号,完成后自动帮我们建立需要的启动文件,库文件。

接下来,创建两个文件夹 Gizwits和Utils 用于存放机智云的数据点和组件

然后将我们从机智云设备下载的通用mcu代码对于文件夹内的文件复制到项目新建立的文件夹内,main文件除外。
接下来,右键项目名称 选择properties->c/c++ General->paths and symbols->includes._gun c 点击add包含我们的库文件

目录地址是工程文件夹下的文件,projname变量能方便我们迁移项目。填写后勾选属于工作空间路径。

接下来,参考通用平台的main文件,为项目自带的main文件添加头文件和函数。
首先是头文件。
  1. #include <string.h>
  2. #include "gizwits_product.h"
  3. #include "common.h"
复制代码
接下来,实现串口接收中断,首先是串口的初始化函数和中断初始化,他们实现的库文件和stm标准库很类似,因此上手还是比较方便的。

初始化完成,编写对应的中断函数,这里会有一点小差别。需要**中断函数。
  1. void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  2. void USART2_IRQHandler(void)
  3. {
  4.     if(USART_GetITStatus(USART2, USART_IT_RXNE)!=RESET)
  5.     {
  6.         uint8_t recvData=USART_ReceiveData(USART2);
  7.         UART_IRQ_FUN(recvData);
  8.     }
  9. }
复制代码
这里,我们在main文件里写中断函数,再调用机智云的函数进行处理。注意**函数。

完成串口接收后,我们要完成串口的发送,直接调用串口发送函数即可,机智云的代码已经写好伪代码和注释。
包含内核头文件
  1. #include "ch32v20x_conf.h"
复制代码
在product文件内完成数据发送

接下来,实现定时器中断,机智云需要一个1ms的定时器中断处理事件。
从数据手册可以得知,定时器挂载在APB1 并且在apb1预分频不为1的情况下,时钟的频率是apb1的2倍。

一般没修改过apb1为2分频,在时钟频率为96mhz情况下,定时器频率也是96mhz
因此生成1ms的中断需要预分频96-1 重装载值1000-1
定时器初始化代码

完成定时器中断,并将中断提供给机智云协议依赖的函数。

  1. void TIM2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  2. void TIM2_IRQHandler(void){
  3.     if( TIM_GetITStatus(TIM2, TIM_IT_Update) == SET ){
  4.         TIMER_IRQ_FUN();
  5.         TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  6.     }
  7. }
复制代码
编写一个简单的开关灯示例测试是否正常。
  1. if(0x01 == currentDataPoint.valueLED_OnOff_1)
  2.             {
  3.             //user handle
  4.                 GPIO_ResetBits(GPIOA, GPIO_Pin_0);
  5.             }
  6.             else
  7.             {
  8.             //user handle
  9.                 GPIO_SetBits(GPIOA, GPIO_Pin_0);
  10.             }
  11.             break;
复制代码
此时,项目已经能正常编译了,我们把项目烧录到开发板,并且将串口连接到esp8266模组测试,通过数据手册可以得知对应串口的复用引脚,我这里是pa2->tx  pa3->rx

效果:



您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

加入Q群 返回顶部

版权与免责声明 © 2006-2024 Gizwits IoT Technology Co., Ltd. ( 粤ICP备11090211号 )

快速回复 返回顶部 返回列表