ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

RISC-V MCU 基于 CH32V307 工业物联网平台系统

2022-08-16 10:30:08  阅读:171  来源: 互联网

标签:__ u8 RISC TIM CH32V307 GPIO MCU WCHNET SIZE


RISC-V MCU 基于 CH32V307 工业物联网平台系统

目录

第一部分 设计概述

1.1 设计目的

    在智能工业生产现场中,生产设备的控制依赖于传感器读数以及相关算法
等。而传感器起着至关重要的作用,传感器的驱动和数据传输依赖于微控制器,
系统基于沁恒 CH32V307 微控制器进行数据收集、服务器进行数据处理和,中
间基于服务器通过串口与微控制器进行数据传输处理并通过以太网与服务器交
互。服务器端,可实现数据库、数据可视化显示和设备交互;微控制器端通过
操作系统执行传感器驱动进程、以太网传输进程、工业现场数据显示等进程;
工业控制器端。

1.2 应用领域

    在现代智能工厂等环境下,传感器代替了人工读数操作,但是信号的传输
多基于以太网连接。本作品应用于智能工厂环境通过以太网传输数据将数据发
生至上位机,经过 Python Socket 简单数据接收处理。

1.3 主要技术特点

    微控制器使用了显示屏、温湿度传感器以及以太网模块。控制器驱动温湿
度模块测量温湿度;显示屏显示传感器名称温湿度名称以及数值;以太网采用
芯片自带 10M 处理模块,外接以太网接口,采用官方驱动库进行数据传输。数
据传输至服务器 python socket 进行以太网数据接收处理。

1.4 关键性能指标

  (1) MCU:
    CH32V307VCT6,主频 144MHz,FLASH 和 RAM 四种配置
    288KB FLASH ,32KB RAM
    256KB FLASH ,64KB RAM
    224KB FLASH ,96KB RAM
    192KB FLASH ,128KB RAM
    CH32V307V-R0 是 南京沁恒微电子(WCH) 推出的一款基于 RISC-V 内核的开发板,最高主频为 120Mhz,该开发板芯片为 CH32V307-R0。


主控片上资源

  (2) AHT10:
    温度范围为: 测量范围为 -40 ℃ ~+ 85 ℃ 精度±0.5℃;
    湿度范围为:测量范围为 0% - 100% 精度为±3%RH;
  (3) 以太网:ETH 支持 10M

1.5 主要创新点

    (1) MCU 自带以太网处理模块
    (2) 采用 TCP 连接,数据传输准确

第二部分 系统组成及功能说明

2.1 整体介绍


系统结构

2.2 各模块介绍

(一)开发板

  a) MCU
    MCU 作为核心处理器,驱动周围模块并与外界进行通信。
  b) 温湿度模块
    温湿度传感器测量物理环境的温湿度,由 MCU 驱动,通过 IIC 协议与
MCU 进行数据传输。


温湿度模块

c) 显示屏
    显示屏作为人机交互界面有 MCU 驱动显示。显示内容包括温湿度传感器信
号;温湿度以及数值等内容
d) 以太网模块
    以太网模块为 MCU 外界以太网接口,无相关转接芯片。

(二)服务器

    以 PC 作为服务器接口,使用 Python Socket 建立服务器。通过绑定 IP 以及
端口进行输出传输以及相关数据的处理等内容。

import socket,os
  
server = socket.socket()
server.bind(("192.168.1.100",1000))
server.listen(5)

#数据暂存器
TEMP = [b'H',b'2']

while True:
    conn,addr = server.accept()
    print("Connected to:",addr)
    while True:
        #接收两个字节数据
        data = conn.recv(2)
        #判断接收的字节是否为空,为空则退出
        if not data:
            print("Connected break")
            break
        #将两个字节切片
        info = [data[i:i+1] for i in range(0, len(data), 1)]
        #print(len(info))
        if len(info) == 2 :
            TEMP[0] = info[0]
            TEMP[1] = info[1]
        #字节判断转换输出
        if (TEMP[0] == b'H') :
            print('H',ord(TEMP[1]))
        if (TEMP[0] == b'T') :
            print('T',ord(TEMP[1]))

server.close()

第三部分 完成情况及性能参数

(一)显示屏模块

    显示屏温湿度显示


显示屏温湿度显示

(二)服务器模块


Python Socket TCP连接

第四部分 主控关键代码

点击查看代码
#include "debug.h"
#include "WCHNET.h"
#include "string.h"
#include "lcd.h"
#include "AHT_10.h"

int32_t temperature, humidity;
char temp[2];
 __attribute__((__aligned__(4))) ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB];                        /* MAC接收描述符 ,4字节对齐*/
 __attribute__((__aligned__(4))) ETH_DMADESCTypeDef DMATxDscrTab[ETH_TXBUFNB];                        /* MAC发送描述符,4字节对齐 */

 __attribute__((__aligned__(4))) u8  MACRxBuf[ETH_RXBUFNB*ETH_MAX_PACKET_SIZE];                       /* MAC接收缓冲区,4字节对齐 */
 __attribute__((__aligned__(4))) u8  MACTxBuf[ETH_TXBUFNB*ETH_MAX_PACKET_SIZE];                       /* MAC发送缓冲区,4字节对齐 */


__attribute__((__aligned__(4))) SOCK_INF SocketInf[WCHNET_MAX_SOCKET_NUM];                           /* Socket信息表,4字节对齐 */
const u16 MemNum[8] = {WCHNET_NUM_IPRAW,
                         WCHNET_NUM_UDP,
                         WCHNET_NUM_TCP,
                         WCHNET_NUM_TCP_LISTEN,
                         WCHNET_NUM_TCP_SEG,
                         WCHNET_NUM_IP_REASSDATA,
                         WCHNET_NUM_PBUF,
                         WCHNET_NUM_POOL_BUF
                         };
const u16 MemSize[8] = {WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_IPRAW_PCB),
                          WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_UDP_PCB),
                          WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_PCB),
                          WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_PCB_LISTEN),
                          WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_SEG),
                          WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_IP_REASSDATA),
                          WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_PBUF) + WCHNET_MEM_ALIGN_SIZE(0),
                          WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_PBUF) + WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_POOL_BUF)
                         };
 __attribute__((__aligned__(4)))u8 Memp_Memory[WCHNET_MEMP_SIZE];
 __attribute__((__aligned__(4)))u8 Mem_Heap_Memory[WCHNET_RAM_HEAP_SIZE];
 __attribute__((__aligned__(4)))u8 Mem_ArpTable[WCHNET_RAM_ARP_TABLE_SIZE];


#define RECE_BUF_LEN                          WCHNET_TCP_MSS*2                                   /*socket接收缓冲区的长度,最小为TCP MSS*/

u8 MACAddr[6];                                                                                   /*Mac地址*/
u8 IPAddr[4] = {192,168,1,10};                                                                   /*IP地址*/
u8 GWIPAddr[4] = {192,168,1,1};                                                                  /*网关*/
u8 IPMask[4] = {255,255,255,0};                                                                  /*子网掩码*/
u8 DESIP[4] = {192,168,1,100};                                                                   /*目的IP地址*/

u8 connectStatus=0;
u8 SocketId;                                                                                     /*socket id号*/
u8 SocketRecvBuf[WCHNET_MAX_SOCKET_NUM][RECE_BUF_LEN];                                           /*socket缓冲区*/
u8 MyBuf[RECE_BUF_LEN];
u16 desport=1000;                                                                                /*目的端口号*/
u16 srcport=1000;                                                                                /*源端口号*/



/*********************************************************************
 * @fn      Ethernet_LED_Configuration
 *
 * @brief   set eth data and link led pin
 *
 * @return  none
 */
void Ethernet_LED_Configuration(void)
{
    GPIO_InitTypeDef  GPIO;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    GPIO.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9;
    GPIO.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO);
    Ethernet_LED_LINKSET(1);
    Ethernet_LED_DATASET(1);
}


/*********************************************************************
 * @fn      Ethernet_LED_LINKSET
 *
 * @brief   set eth link led,setbit 0 or 1,the link led turn on or turn off
 *
 * @return  none
 */
void Ethernet_LED_LINKSET(u8 setbit)
{
     if(setbit){
         GPIO_SetBits(GPIOB, GPIO_Pin_8);
     }
     else {
         GPIO_ResetBits(GPIOB, GPIO_Pin_8);
    }
}


/*********************************************************************
 * @fn      Ethernet_LED_DATASET
 *
 * @brief   set eth data led,setbit 0 or 1,the data led turn on or turn off
 *
 * @return  none
 */
void Ethernet_LED_DATASET(u8 setbit)
{
     if(setbit){
         GPIO_SetBits(GPIOB, GPIO_Pin_9);
     }
     else {
         GPIO_ResetBits(GPIOB, GPIO_Pin_9);
    }
}

/*********************************************************************
 * @fn      mStopIfError
 *
 * @brief   check if error.
 *
 * @return  none
 */
void mStopIfError(u8 iError)
{
    if (iError == WCHNET_ERR_SUCCESS) return;                                 /* 操作成功 */
    printf("Error: %02X\r\n", (u16)iError);                                    /* 显示错误 */
}


/*********************************************************************
 * @fn      WCHNET_LibInit
 *
 * @brief   Initializes NET.
 *
 * @return  command status
 */
u8 WCHNET_LibInit(const u8 *ip,const u8 *gwip,const u8 *mask,const u8 *macaddr)
{
    u8 i;
    struct _WCH_CFG  cfg;

    cfg.RxBufSize = RX_BUF_SIZE;
    cfg.TCPMss   = WCHNET_TCP_MSS;
    cfg.HeapSize = WCH_MEM_HEAP_SIZE;
    cfg.ARPTableNum = WCHNET_NUM_ARP_TABLE;
    cfg.MiscConfig0 = WCHNET_MISC_CONFIG0;
    WCHNET_ConfigLIB(&cfg);
    i = WCHNET_Init(ip,gwip,mask,macaddr);
    return (i);
}

/*********************************************************************
 * @fn      SET_MCO
 *
 * @brief   Set ETH Clock.
 *
 * @return  none
 */
void SET_MCO(void)
{

    RCC_PLL3Cmd(DISABLE);
    RCC_PREDIV2Config(RCC_PREDIV2_Div2);
    RCC_PLL3Config(RCC_PLL3Mul_15);
    RCC_MCOConfig(RCC_MCO_PLL3CLK);
    RCC_PLL3Cmd(ENABLE);
    Delay_Ms(100);
    while(RESET == RCC_GetFlagStatus(RCC_FLAG_PLL3RDY))
    {
        Delay_Ms(500);
    }
    RCC_AHBPeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
}

/*********************************************************************
 * @fn      TIM2_Init
 *
 * @brief   Initializes TIM2.
 *
 * @return  none
 */
void TIM2_Init( void )
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure={0};

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    TIM_TimeBaseStructure.TIM_Period = 200-1;
    TIM_TimeBaseStructure.TIM_Prescaler =7200-1;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    TIM_ITConfig(TIM2, TIM_IT_Update ,ENABLE);

    TIM_Cmd(TIM2, ENABLE);
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update );
    NVIC_SetPriority(TIM2_IRQn, 0x80);
    NVIC_EnableIRQ(TIM2_IRQn);
}


/*********************************************************************
 * @fn      WCHNET_CreatTcpSocket
 *
 * @brief   Creat Tcp Socket
 *
 * @return  none
 */
void WCHNET_CreatTcpSocket(void)
{
   u8 i;
   SOCK_INF TmpSocketInf;                                                       /* 创建临时socket变量 */

   memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF));                            /* 库内部会将此变量复制,所以最好将临时变量先全部清零 */
   memcpy((void *)TmpSocketInf.IPAddr,DESIP,4);                                 /* 设置目的IP地址 */
   TmpSocketInf.DesPort  = desport;                                             /* 设置目的端口 */
   TmpSocketInf.SourPort = srcport++;                                           /* 设置源端口 */
   TmpSocketInf.ProtoType = PROTO_TYPE_TCP;                                     /* 设置socekt类型 */
   TmpSocketInf.RecvStartPoint = (u32)SocketRecvBuf[SocketId];                  /* 设置接收缓冲区的接收缓冲区 */
   TmpSocketInf.RecvBufLen = RECE_BUF_LEN ;                                     /* 设置接收缓冲区的接收长度 */
   i = WCHNET_SocketCreat(&SocketId,&TmpSocketInf);                             /* 创建socket,将返回的socket索引保存在SocketId中 */
   printf("WCHNET_SocketCreat %d\r\n",SocketId);
   mStopIfError(i);                                                             /* 检查错误 */
   i = WCHNET_SocketConnect(SocketId);                                          /* TCP连接 */
   mStopIfError(i);                                                             /* 检查错误 */
   printf("Error= %d\r\n",i);
}

/*********************************************************************
 * @fn      WCHNET_HandleSockInt
 *
 * @brief   Socket Interrupt Handle
 *
 * @return  none
 */
void WCHNET_HandleSockInt(u8 sockeid,u8 initstat)
{
    u32 len;

    if(initstat & SINT_STAT_RECV)                                               /* socket接收中断*/
    {
       len = WCHNET_SocketRecvLen(sockeid,NULL);                                /* 获取socket缓冲区数据长度  */
       printf("WCHNET_SocketRecvLen %d  %d\r\n",len,sockeid);
       WCHNET_SocketRecv(sockeid,MyBuf,&len);                                   /* 获取socket缓冲区数据 */
    }
    if(initstat & SINT_STAT_CONNECT)                                            /* socket连接成功中断*/
    {
        printf("TCP Connect Success\r\n");
        WCHNET_ModifyRecvBuf(sockeid, (u32)SocketRecvBuf[sockeid], RECE_BUF_LEN);
    }
    if(initstat & SINT_STAT_DISCONNECT)                                         /* socket连接断开中断*/
    {
        printf("TCP Disconnect\r\n");
    }
    if(initstat & SINT_STAT_TIM_OUT)                                            /* socket连接超时中断*/
    {
       printf("TCP Timout\r\n");                                                /* 延时200ms,重连*/
    }
}


/*********************************************************************
 * @fn      WCHNET_HandleGlobalInt
 *
 * @brief   Global Interrupt Handle
 *
 * @return  none
 */
void WCHNET_HandleGlobalInt(void)
{
    u8 initstat;
    u16 i;
    u8 socketinit;

    initstat = WCHNET_GetGlobalInt();                                           /* 获取全局中断标志*/
    if(initstat & GINT_STAT_UNREACH)                                            /* 不可达中断 */
    {
       printf("GINT_STAT_UNREACH\r\n");
    }
   if(initstat & GINT_STAT_IP_CONFLI)                                           /* IP冲突中断 */
   {
       printf("GINT_STAT_IP_CONFLI\r\n");
   }
   if(initstat & GINT_STAT_PHY_CHANGE)                                          /* PHY状态变化中断 */
   {
       i = WCHNET_GetPHYStatus();                                               /* 获取PHY连接状态*/
       if(i&PHY_Linked_Status)
       printf("PHY Link Success\r\n");
   }
   if(initstat & GINT_STAT_SOCKET)                                              /* Socket中断*/
   {
       for(i = 0; i < WCHNET_MAX_SOCKET_NUM; i ++)
       {
           socketinit = WCHNET_GetSocketInt(i);                               /* 获取socket中断并清零  */
           if(socketinit)WCHNET_HandleSockInt(i,socketinit);                  /* Èç¹ûÓÐÖжÏÔòÇåÁã */
       }
   }
}

void led_gpio(){
    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOE, &GPIO_InitStructure);
}

void Refresh_TIM_Init( u16 arr, u16 psc)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;

    RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM7, ENABLE );

    TIM_TimeBaseInitStructure.TIM_Period = arr;
    TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Down;
    TIM_TimeBaseInit( TIM7, &TIM_TimeBaseInitStructure);
    TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE);

    TIM_ARRPreloadConfig( TIM7, ENABLE );
    TIM_Cmd( TIM7, ENABLE );

    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn ;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;        //子优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

void TIM7_IRQHandler(void)   __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM7_IRQHandler(void)
{
    uint32_t len = 1;
     char old1 = temperature, old2 = humidity ;

        if(old1 != temp[0])
        {
            old1 = temp[0];
            WCHNET_SocketSend(SocketId,"T",&len);
            WCHNET_SocketSend(SocketId,temp,&len);
        }
        if(old2 != temp[1])
        {
            old2 = temp[1];
            WCHNET_SocketSend(SocketId,"H",&len);
            WCHNET_SocketSend(SocketId,(temp+1),&len);
        }
    TIM_ClearFlag(TIM7, TIM_FLAG_Update);//清除标志位
}
int main(void)
{
    u8 i;

    Delay_Init();
    USART_Printf_Init(115200);

    lcd_init();
        printf("width:%02d height:%02d \n", LCD_W, LCD_H);
        lcd_clear(BLACK);
        lcd_show_string(25, 10, 32, "   Logstic");
        lcd_set_color(BLACK, RED);
        delay_ms(100);

        Refresh_TIM_Init( 200-1, (SystemCoreClock/10000)-1 );

        lcd_set_color(BLACK,WHITE);
        lcd_show_string(0, 70, 16,"AHT10");
        while(AHT10_Init())         //初始化AHT10
        {
            printf("AHT10 Error");
            lcd_set_color(BLACK,RED);
            lcd_show_string(180, 176, 16,"Error");
            Delay_Ms(200);
            lcd_show_string(180, 176, 16,"     ");
            Delay_Ms(200);
        }

                                              /*串口打印初始化*/
	printf("TcpClient Test\r\n");
	led_gpio();
    SET_MCO();
    TIM2_Init();
    WCH_GetMac(MACAddr);                                                     /*获取芯片Mac地址*/
    i=WCHNET_LibInit(IPAddr,GWIPAddr,IPMask,MACAddr);                        /*以太网库初始化*/
    mStopIfError(i);
    if(i==WCHNET_ERR_SUCCESS) printf("WCHNET_LibInit Success\r\n");
    while(!(WCHNET_GetPHYStatus()&PHY_LINK_SUCCESS))                         /*等待PHY连接成功*/
     {
       Delay_Ms(100);
     }
    WCHNET_CreatTcpSocket();                                                 /*创建Tcp socket*/

	while(1)
	{

	    temperature = AHT10_Read_Temperature();
	    humidity = AHT10_Read_Humidity();
	    temp[0] = (char)(temperature);
	    temp[1] = (char)(humidity);

        WCHNET_MainTask();                                                     /*以太网库主任务函数,需要循环调用*/
      if(WCHNET_QueryGlobalInt())                                            /*查询以太网全局中断,如果有中断,调用全局中断处理函数*/
      {
         WCHNET_HandleGlobalInt();
      }



	    lcd_set_color(BLACK,WHITE);
	    lcd_show_string(0, 70, 16,"AHT10");
	    while(AHT10_Init())         //初始化AHT10
	    {
	        printf("AHT10 Error");
	        lcd_set_color(BLACK,RED);
	        lcd_show_string(180, 176, 16,"Error");
	        Delay_Ms(200);
	        lcd_show_string(180, 176, 16,"     ");
	        Delay_Ms(200);
	    }
        temperature = AHT10_Read_Temperature();
        humidity = AHT10_Read_Humidity();
        lcd_set_color(BLACK,GREEN);
        lcd_show_string(30, 92, 16,"Temperature : %5d", (int)(temperature));
        lcd_show_string(30, 108, 16,"Humidity    : %5d", (int)(humidity));

    }
}

Gitee开源仓库:https://gitee.com/slick-zhang/CH32V307demo.git

标签:__,u8,RISC,TIM,CH32V307,GPIO,MCU,WCHNET,SIZE
来源: https://www.cnblogs.com/jackzhang001/p/16590472.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有