首页 > 其他分享 >CH58x/59x SPI0代码参考

CH58x/59x SPI0代码参考

时间:2024-08-22 17:49:04浏览次数:14  
标签:DMA SPI0 59x R8 SPI CH58x RB GPIO

前言:

代码参考为首字节模式和数据流模式,均使用DMA,建议使用数据流DMA。

一、数据流/首字节收发代码参考

数据流流程:

  1. 主机定时器1ms间隔发送;
  2. 从机接收数据;
  3. 从机填入发送数据到DMA并通知主机接收;
  4. 主机DMA接收数据;

首字节流程:

  1. 主机定时器1ms间隔发送;
  2. 从机首字节接收并DMA接收完整数据;
  3. 从机DMA发送数据并通知主机接收;
  4. 主机DMA接收数据;

主机收发代码:

#include "CH59x_common.h"

#define FSTMODE 0
__attribute__((aligned(4))) UINT8 tx_buff[32] ={0x1,0x55,0x2,0x55,0x3,0x55,0x4,0x55,0x5,0x55,
                                                0x1,0x55,0x2,0x55,0x3,0x55,0x4,0x55,0x5,0x55,
                                                0x1,0x55,0x2,0x55,0x3,0x55,0x4,0x55,0x5,0x55,
                                                0x1,0x55};
__attribute__((aligned(4))) UINT8 rx_buff[32];
uint8_t tx_len[60] = {0};
volatile uint8_t buf_judge[10];

void DebugInit(void)
{
    GPIOA_SetBits(GPIO_Pin_9);
    GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);
    GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA);
    UART1_DefInit();
    UART1_BaudRateCfg(1500000);
}

VOID SPI_Init(){
    GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_PU);/*用于从机通知主机提供时钟,从机准备发送数据*/
    GPIOA_ITModeCfg(GPIO_Pin_4, GPIO_ITMode_FallEdge);
    PFIC_EnableIRQ(GPIO_A_IRQn);

    GPIOA_SetBits(GPIO_Pin_12);
    GPIOA_ModeCfg(GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14, GPIO_ModeOut_PP_5mA);
    GPIOA_ModeCfg(GPIO_Pin_15, GPIO_ModeIN_PU);
    SPI0_MasterDefInit();
    SPI0_CLKCfg(4);
    PFIC_EnableIRQ(SPI0_IRQn);

    tx_len[0] = sizeof(tx_buff);
    printf("tx_playload[0]:%d\n", tx_len[0]);
    for (uint8_t i=0; i<sizeof(tx_buff); i++)
    {
        tx_len[1+i] = tx_buff[i];
    }
    PRINT("SPI0 Master Init\n");
}

int main()
{
    SetSysClock(CLK_SOURCE_PLL_60MHz);

    DebugInit();/* 配置串口调试 */
    PRINT("Start @ChipID=%02X\n", R8_CHIP_ID);

    TMR0_TimerInit(FREQ_SYS / 1000);       // 设置定时时间 1ms
    TMR0_ITCfg(ENABLE, TMR0_3_IT_CYC_END); // 开启中断
    PFIC_EnableIRQ(TMR0_IRQn);

    while(1){
        if(buf_judge[0] != 0){
            printf("%x %x\n",buf_judge[0], buf_judge[1]);
            buf_judge[0] = 0;
        }
    }
}

__INTERRUPT
__HIGH_CODE
void SPI0_IRQHandler(void)
{
    if(R8_SPI0_INT_FLAG & RB_SPI_IF_DMA_END)
    {
        if(R8_SPI0_CTRL_MOD&RB_SPI_FIFO_DIR)
        {
            GPIOA_SetBits(GPIO_Pin_12);
            buf_judge[0] = rx_buff[30];
            buf_judge[1] = rx_buff[31];
            R8_SPI0_CTRL_CFG &= ~RB_SPI_DMA_ENABLE;
            R16_SPI0_DMA_BEG = 0x3300;                 //更改DMA地址,出中断
            R8_SPI0_INT_FLAG |= RB_SPI_IF_DMA_END|RB_SPI_IF_CNT_END;
            R8_SPI0_INTER_EN &=~ (RB_SPI_IE_DMA_END|RB_SPI_IE_CNT_END);
            R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR;
        }
        if(!(R8_SPI0_CTRL_MOD&RB_SPI_FIFO_DIR))//主机发送
        {
            R8_SPI0_INT_FLAG |= RB_SPI_IF_DMA_END;
        }
    }
    if((R8_SPI0_INT_FLAG & RB_SPI_IF_CNT_END)&&(!(R8_SPI0_CTRL_MOD&RB_SPI_FIFO_DIR)))
    {
        GPIOA_SetBits(GPIO_Pin_12);
        R8_SPI0_CTRL_CFG &= ~RB_SPI_DMA_ENABLE;
        R16_SPI0_DMA_BEG = 0x4300;                 //更改DMA地址,出中断
        R8_SPI0_INT_FLAG |= RB_SPI_IF_DMA_END|RB_SPI_IF_CNT_END;
        R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR;
        R8_SPI0_INTER_EN &=~ (RB_SPI_IE_DMA_END|RB_SPI_IE_CNT_END);
    }
}

__INTERRUPT
__HIGH_CODE
void GPIOA_IRQHandler(void)
{
    GPIOA_ClearITFlagBit(GPIO_Pin_4);
    GPIOA_ResetBits(GPIO_Pin_12);
    R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR;
    R16_SPI0_DMA_BEG = ((uint32_t)rx_buff);//从机先填DMA,主机再接收
    R16_SPI0_DMA_END = ((uint32_t)rx_buff+32);
    R16_SPI0_TOTAL_CNT = 32;
    R8_SPI0_INTER_EN |= RB_SPI_IE_DMA_END;
    R8_SPI0_CTRL_CFG |= RB_SPI_DMA_ENABLE;
}

__INTERRUPT
__HIGH_CODE
void TMR0_IRQHandler(void) // TMR0 定时中断
{
    if(TMR0_GetITFlag(TMR0_3_IT_CYC_END))
    {
        TMR0_ClearITFlag(TMR0_3_IT_CYC_END); // 清除中断标志
        GPIOA_ResetBits(GPIO_Pin_12);
        R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR;
#if FSTMODE
        R16_SPI0_DMA_BEG = (uint32_t)tx_len;
        R16_SPI0_DMA_END = (uint32_t)(tx_len + (1+sizeof(tx_buff)));
        R16_SPI0_TOTAL_CNT = (1+sizeof(tx_buff));
#else
        R16_SPI0_DMA_BEG = (uint32_t)tx_buff;
        R16_SPI0_DMA_END = (uint32_t)(tx_buff+32);
        R16_SPI0_TOTAL_CNT = 32;
#endif
        R8_SPI0_INTER_EN |= RB_SPI_IE_DMA_END;
        R8_SPI0_CTRL_CFG |= RB_SPI_DMA_ENABLE;
    }
}

从机收发代码:

#include "CH59x_common.h"

#define FSTMODE 0
__attribute__((aligned(4))) UINT8 tx_buff[32]={0x1,0xaa,0x2,0xaa,0x3,0xaa,0x4,0xaa,0x5,0xaa,
                                                0x1,0xaa,0x2,0xaa,0x3,0xaa,0x4,0xaa,0x5,0xaa,
                                                0x1,0xaa,0x2,0xaa,0x3,0xaa,0x4,0xaa,0x5,0xaa,
                                                0x1,0xaa,};
__attribute__((aligned(4))) UINT8 rx_buff[32];
volatile uint8_t buf_judge[10];
volatile uint8_t len = 0;

void DebugInit(void)
{
    GPIOA_SetBits(GPIO_Pin_9);
    GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);
    GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA);
    UART1_DefInit();
    UART1_BaudRateCfg(1500000);
}

VOID SPI_Init(){    /* 设备模式 */
    GPIOA_SetBits(GPIO_Pin_4);//PA4用于触发主机中断
    GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeOut_PP_5mA);

    GPIOA_ModeCfg(GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14, GPIO_ModeIN_PU);/*SPI0 GPIOInit*/
    GPIOA_ModeCfg(GPIO_Pin_14, GPIO_ModeIN_PU);
    GPIOA_SetBits(GPIO_Pin_15);
    GPIOA_ModeCfg(GPIO_Pin_15, GPIO_ModeOut_PP_5mA);

#if FSTMODE
    R8_SPI0_CTRL_MOD = RB_SPI_ALL_CLEAR;
    R8_SPI0_CTRL_MOD = RB_SPI_MODE_SLAVE;
    R8_SPI0_CTRL_MOD |= RB_SPI_SLV_CMD_MOD;     //首字节命令模式
    R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR;        //输入模式,接收数据
    R8_SPI0_CTRL_MOD &= ~(RB_SPI_MOSI_OE | RB_SPI_SCK_OE);
    R8_SPI0_CTRL_MOD |= RB_SPI_MISO_OE ;
    R8_SPI0_INTER_EN = RB_SPI_IE_FST_BYTE;
    PFIC_EnableIRQ(SPI0_IRQn);
#else
    R8_SPI0_CTRL_MOD = RB_SPI_ALL_CLEAR;
    R8_SPI0_CTRL_MOD = RB_SPI_MODE_SLAVE;
    R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR;        //输入模式,接收数据
    R8_SPI0_CTRL_MOD &= ~(RB_SPI_MOSI_OE | RB_SPI_SCK_OE);
    R8_SPI0_CTRL_MOD |= RB_SPI_MISO_OE ;

    R16_SPI0_DMA_BEG = (UINT32)(rx_buff);
    R16_SPI0_DMA_END = (UINT32)((rx_buff)+32);
    R16_SPI0_TOTAL_CNT = 32;
    R8_SPI0_CTRL_CFG |= RB_SPI_DMA_ENABLE;
    R8_SPI0_INTER_EN |= RB_SPI_IE_DMA_END;

    PFIC_EnableIRQ(SPI0_IRQn);
#endif
    PRINT("SPI0 Slave Init\n");
}

int main()
{
    SetSysClock(CLK_SOURCE_PLL_60MHz);
    DebugInit();
    PRINT("Start @ChipID=%02X\n", R8_CHIP_ID);
    SPI_Init();
    while(1){
        if(buf_judge[0] != 0){
            printf("%x %x\n", buf_judge[0], buf_judge[1]);
            buf_judge[0] = 0;
        }
    }
}

#if FSTMODE
__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode")))
void SPI0_IRQHandler(void)
{
    if((R8_SPI0_INT_FLAG & RB_SPI_IF_FST_BYTE)&&(R8_SPI0_CTRL_MOD&RB_SPI_FIFO_DIR)){ //已接收到首字节
        len = R8_SPI0_FIFO;
        R16_SPI0_DMA_BEG = (UINT32)(rx_buff);
        R16_SPI0_DMA_END = (UINT32)((rx_buff)+len);
        R16_SPI0_TOTAL_CNT = len;
        R8_SPI0_CTRL_CFG |= RB_SPI_DMA_ENABLE;
        R8_SPI0_INTER_EN &= ~RB_SPI_IE_FST_BYTE;
        R8_SPI0_INT_FLAG |= RB_SPI_IF_FST_BYTE;//清除单字节传输完成标志位
        R8_SPI0_INTER_EN |= RB_SPI_IE_DMA_END ;
        R8_SPI0_CTRL_MOD &= ~RB_SPI_SLV_CMD_MOD;
    }
    if((R8_SPI0_INT_FLAG & RB_SPI_IF_DMA_END)&&(R8_SPI0_CTRL_MOD&RB_SPI_FIFO_DIR))
    {
        buf_judge[0] = rx_buff[30];
        buf_judge[1] = rx_buff[31];
        R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR;
        R8_SPI0_INTER_EN &= ~RB_SPI_IE_FST_BYTE;

        R16_SPI0_DMA_BEG = (UINT32)(tx_buff); //从机先填DMA,主机再接收
        R16_SPI0_DMA_END = (UINT32)((tx_buff)+32);
        R16_SPI0_TOTAL_CNT = 32;
        R8_SPI0_INT_FLAG = RB_SPI_IF_DMA_END;//xxx 不要进中断立马清除标志
        GPIOA_ResetBits(GPIO_Pin_4);//xxx 从机发送中断通知脚。从机先填DMA,主机再接收
        GPIOA_SetBits(GPIO_Pin_4);
    }
    if((R8_SPI0_INT_FLAG & RB_SPI_IF_CNT_END)&&(!(R8_SPI0_CTRL_MOD&RB_SPI_FIFO_DIR)))
    {
        R16_SPI0_DMA_BEG = 0;//xxx 需要等到主机接收DMA数据完成才可以修改地址,否则主机接收数据会被篡改
        R8_SPI0_INT_FLAG |= RB_SPI_IF_CNT_END;
        R8_SPI0_CTRL_MOD |= RB_SPI_SLV_CMD_MOD|RB_SPI_FIFO_DIR;
        R8_SPI0_INTER_EN = RB_SPI_IE_FST_BYTE;
        R8_SPI0_CTRL_CFG &= ~RB_SPI_DMA_ENABLE;
    }
}
#else
__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode")))
void SPI0_IRQHandler(void)
{
    if((R8_SPI0_INT_FLAG & RB_SPI_IF_DMA_END)&&(R8_SPI0_CTRL_MOD&RB_SPI_FIFO_DIR)){
        buf_judge[0] = rx_buff[30];
        buf_judge[1] = rx_buff[31];
        R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR;

        R16_SPI0_DMA_BEG = (UINT32)(tx_buff); //从机先填DMA,主机再接收
        R16_SPI0_DMA_END = (UINT32)((tx_buff)+32);
        R16_SPI0_TOTAL_CNT = 32;
        R8_SPI0_INT_FLAG |= RB_SPI_IF_DMA_END;//xxx 不要进中断立马清除标志
        GPIOA_ResetBits(GPIO_Pin_4);//xxx 从机发送中断通知脚。从机先填DMA,主机再接收
        GPIOA_SetBits(GPIO_Pin_4);
    }
    if((R8_SPI0_INT_FLAG & RB_SPI_IF_CNT_END)&&(!(R8_SPI0_CTRL_MOD&RB_SPI_FIFO_DIR))){
        R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR;

        R16_SPI0_DMA_BEG = (UINT32)(rx_buff);
        R16_SPI0_DMA_END = (UINT32)((rx_buff)+32);
        R16_SPI0_TOTAL_CNT = 32;
        R8_SPI0_INT_FLAG |= RB_SPI_IF_CNT_END;
    }
}
#endif

二、波形参考:

三、注意点

 

标签:DMA,SPI0,59x,R8,SPI,CH58x,RB,GPIO
From: https://www.cnblogs.com/gscw/p/18374437

相关文章

  • ch58x/ch59xADC差分采样NTC电阻获取当前温度
    前言:之前的文章中也有关于使用I2C器件进行温度的采集的文章采集温度的方式不止使用传感器,也可以使用NTC温敏电阻进行采集,此方法的外围电路较为简单切成本较低,代码也较为容易实现。实现原理:先通过差分采样电路进行采集,采集之后可以获取NTC或者定值电阻的电压;已知这些信息可以通过......
  • CH57x/CH58x/CH59x获取从机广播信息
    有时需要通过主机设备(MCU非手机)获取从设备的广播信息例如广播包,MAC地址,扫描应答包等以下的程序片段及功能实现是在WCH的CH59X的observer例程上实现的;1、获取广播包所有的函数在库函数中都可以找到,具体实现函数如下:caseGAP_DEVICE_INFO_EVENT:{Observ......
  • CH57x/CH58X/CH59X/CH32F/V208OTA使用说明
    目前提供了两种OTA升级方式,方式一:带库升级;每次升级可以带着库一起进行升级(带库升级适用于flash较大的芯片)方式二:固定库升级;升级时库不会随着升级而升级(适用于flash不够用时)方式一:升级时需要同时烧录这三个固件:(可以使用isp工具同时烧录也可以使用合并工具将三个工程合并后再烧......
  • CH58x芯片Hardfault问题排查
    前言:针对RISC-V芯片进入HardFault_Handler函数的问题排查提供讲解。一、HardFault函数添加PC指针打印在公共文件的sys.c函数中找到函数并修改如下:__INTERRUPT__HIGH_CODE__attribute__((weak))voidHardFault_Handler(void){uint32_tv_mepc,v_mcause,v_mtval;p......
  • 低功耗蓝牙系列芯片CH57x,CH58x,CH59x实现蓝牙多通道配对/回连同一台电脑或多台电脑实
    依旧以老朋友CH583为例,我们随便打开一个HID例程,还是以HID_Keyboard例程做讲解:1、直奔主题到我们的库函数初始化函数中去,红圈圈中的SNVAddr配置信息为我们此次配对连接后所获取到的信息存储的地址区,配对信息中包含:对方MAC地址,设备信息,协商所得IRK密钥等关键信息,都会保存到SNVAddr......
  • CH57x,CH58x,CH59x芯片_SPI借助GPIO中断完成中断传输
    受其他项目的启发,如果IO充裕,且在SPI主机与SPI从机均可以自行编程的情况下,可以尝试在4线SPI的基础上增加两根GPIO线,通过IO中断的形式通知对方进行收数据;非SPI中断形式,以两颗CH582通讯为例,1、主机程序:voidmain(){SetSysClock(CLK_SOURCE_PLL_60MHz);GPIOA_ModeCfg......
  • Spectrum 模拟数据采集卡--M2p.59xx-x4 多达8通道同步采集,5M~125MSPS 采样率,16bit
    M2p.59xx-x4-高达125MS/s的16位数字转换器 该卡512MSample板载内存,并支持standard采集、FIFO采集、门采样,ABA等多种采集模式和时间戳。支持Windows/Linux32位和64位的操作系统驱动程序,支持C/C++,LabVIEW(Windows),MATLAB(Windows和Linux),LabWindows/CVI,IVI,.NET,Delphi,VisualBasic,Ja......
  • CH59X/CH58X/CH57X 片上flash的使用
    以CH592F为例;在使用时先看手册对code和data区的划分一、DataFlash的读写的操作 先看几个操作dataflash的API(读擦写);/***@briefreadData-Flashdatablock**@paramStartAddr-Addressofthedatatoberead.//要读取的数据的地址,传入的的地址是相对地址所......
  • 【沁恒 CH58x 应用】BLE相关知识基础
    大纲:1.什么是ble,ble与传统蓝牙的区别,ble与蓝牙4.0的区别2.ble的基本概念:协议层(协议框架)、服务(Service)、特征(Characteristic)。什么是配对(pair)、通知(notify)。 介绍低功耗蓝牙1.什么是低功耗蓝牙?图1BLE介绍低功耗蓝牙,简称BLE,是蓝牙的一种省电变体。BLE的主要应......
  • 目录:CH57x/CH58x/CH59x/CH32V208低功耗蓝牙应用
    外设相关:CH59x系统16位PWM使用-小舟从此逝_1-博客园(cnblogs.com)CH59X/CH58X/CH57XPWM使用-小舟从此逝_1-博客园(cnblogs.com) CH58x/CH57x硬件SPI操作外部flash学习记录-小舟从此逝_1-博客园(cnblogs.com)BLE相关:CH592/CH582/CH573/CH579服务修改-小......