avatar

松果工作室

欢迎光临

  • 首页
  • freeRTOS
  • ESP
  • 开发手册
  • 快速笔记
  • 个人收藏
  • 工具
Home CH573(一) 基础外设
文章

CH573(一) 基础外设

Posted 2024-05-29 Updated 2024-09- 22
By YCP
53~68 min read

教程来自链接

不得不吐槽一下, 沁恒的库真的很浅, 和 STM 的 HAL 库比,通过两个跳转就能看见它的寄存器操作,麻了. 好吧好处就是能让我知道原理, 坏处就是调用草率,不容易懂.

(一) 点灯

#include "CH57x_common.h"

int main(){
  SetSysClock(CLK_SOURCE_PLL_60MHz);
  GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeOut_PP_5mA);
  while(1){
    GPIOA_ResetBits(GPIO_Pin_8); //LED点亮
    mDelaymS(1000);					//持续0.5s
    GPIOA_SetBits(GPIO_Pin_8); 	//LED熄灭
    mDelaymS(1000);					//持续0.5s
  }
}

(二) 按键输入

#include "CH57x_common.h"

#define KEY1_PIN GPIO_Pin_22

int main()
{
    SetSysClock(CLK_SOURCE_PLL_60MHz);
    GPIOB_ModeCfg(GPIO_Pin_22, GPIO_ModeIN_PU);//KEY1_PIN上拉输入
    while(1)
    {
        if(GPIOA_ReadPortPin(KEY1_PIN)==0){
            DelayMs(10);
            if(GPIOA_ReadPortPin(KEY1_PIN)==0){
                //do nothing
            }
        }
        DelayMs(50);
    }
}

(三) 中断

#include "CH57x_common.h"

#define KEY1_PIN GPIO_Pin_4

int main() {
    SetSysClock(CLK_SOURCE_PLL_60MHz);
    GPIOB_ModeCfg(KEY1_PIN, GPIO_ModeIN_PU);       //KEY3_PIN设置为上拉输入
    GPIOB_ITModeCfg(KEY1_PIN, GPIO_ITMode_FallEdge);//KEY3_PIN下降沿触发中断
    PFIC_EnableIRQ(GPIO_B_IRQn);                   //使能GPIOB端口中断

    while (1) {
        DelayMs(50);
    }
}

//设置外部中断相关函数属性,指定声明相关特征
__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode")))
/*
 * 函数名:GPIOB_IRQHandler
 * 参数:无
 * 返回值:无
 * 功能说明:GPIOB端口的中断处理函数
 */
void GPIOB_IRQHandler(void) {
    //判断GPIOB端口的中断标志
    if (GPIOB_ReadITFlagBit(KEY1_PIN)) {
        //do nothing
    }
    //清空中断标志位
    GPIOB_ClearITFlagBit(KEY1_PIN);
}

(四) 定时器

#include "CH57x_common.h"

int main() {
    SetSysClock(CLK_SOURCE_PLL_60MHz);

    uint32_t time = 500;//定时500ms
    TMR0_TimerInit(FREQ_SYS / (1000 / time));//定时器0初始化:
    TMR0_ITCfg(ENABLE, TMR0_3_IT_CYC_END); // 开启中断
    PFIC_EnableIRQ(TMR0_IRQn);

    while (1) {
        DelayMs(50);
    }
}

__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode")))
/*********************************************************************************************************
* 函 数 名: TMR0_IRQHandler()
* 功能说明: 定时器TMR0中断函数(LED翻转电平)
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************/
void TMR0_IRQHandler(void) {
    if (TMR0_GetITFlag(TMR0_3_IT_CYC_END)) {
        TMR0_ClearITFlag(TMR0_3_IT_CYC_END); // 清除中断标志
        //do nothing
    }
}

(五) PWM

#include "CH57x_common.h"

int main() {
    SetSysClock(CLK_SOURCE_PLL_60MHz);

    //基于定时器的引脚PWM初始化:PA9\PA10\PA11\PB22
    GPIOB_ResetBits(GPIO_Pin_22); // 配置PWM口 PB22
    GPIOB_ModeCfg(GPIO_Pin_22, GPIO_ModeOut_PP_5mA);
    TMR3_PWMInit(High_Level, PWM_Times_1);
    TMR3_PWMCycleCfg(6000); // 周期 100us

    //PWM引脚初始化:PB14\PB7\PB4\PB23\PA13\PA12\PB6\PB0:
    GPIOA_ModeCfg(GPIO_Pin_12, GPIO_ModeOut_PP_5mA);  // PA12 - PWM4
    PWMX_CLKCfg(4);                                   // cycle = 4/Fsys
    PWMX_CycleCfg(PWMX_Cycle_64);                     // 周期 = 64*cycle
    PWMX_ACTOUT(CH_PWM4, 64 / 4, Low_Level, ENABLE);  // 25% 占空比

    while (1) {
        //呼吸灯1
        for (uint16_t i = 0; i < 6000; i += 20) {
            TMR3_Disable();
            TMR3_PWMActDataWidth(i); //修改占空比必须暂时关闭定时器
            TMR3_Enable();
            DelayMs(2);
        }
        for (uint16_t i = 6000; i > 0; i -= 20) {
            TMR3_Disable();
            TMR3_PWMActDataWidth(i); // 修改占空比必须暂时关闭定时器
            TMR3_Enable();
            DelayMs(2);
        }
        //呼吸灯2
        for (uint16_t i = 1; i < 64; i++) {
            PWMX_ACTOUT(CH_PWM4, 64 / i, Low_Level, ENABLE);
            DelayMs(5);
        }
        for (uint16_t i = 64; i > 1; i--) {
            PWMX_ACTOUT(CH_PWM4, 64 / i, Low_Level, ENABLE);
            DelayMs(5);
        }
    }
}

(六) 串口

#include "CH57x_common.h"
uint8_t Tx0Buff[] = "Hello by UART0 --- FUNIOT.XYZ!\r\n";
uint8_t Rx0Buff[100];

int main()
{
    SetSysClock(CLK_SOURCE_PLL_60MHz);

    /* 配置串口0:先配置IO口模式,再配置串口 */
    GPIOB_SetBits(GPIO_Pin_7);
    GPIOB_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_PU);      // RXD0-配置上拉输入
    GPIOB_ModeCfg(GPIO_Pin_7, GPIO_ModeOut_PP_5mA); // TXD0-配置推挽输出,注意先让IO口输出高电
    UART0_DefInit();  //初始化默认配置,波特率115200
    //配置串口0中断接收模式
    UART0_ByteTrigCfg(UART_7BYTE_TRIG);
    UART0_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_LINE_STAT);
    PFIC_EnableIRQ(UART0_IRQn);

    while(1)
    {
        UART0_SendString(Tx0Buff, sizeof(Tx0Buff));
        DelayMs(2000);
    }
}

__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode")))
void UART0_IRQHandler(void)
{
    volatile uint8_t i;
    if(UART_II_RECV_TOUT) // 接收超时,暂时一帧数据接收完成
    {
        i = UART0_RecvString(Rx0Buff);   //接收数据并记录长度
        UART0_SendString(Rx0Buff, i);    //将接收的数据串口发送
        //自行数据解析
    }
}

(七) ADC

/********************************** (C) COPYRIGHT *******************************
 * File Name          : Main.c
 * Author             : WCH
 * Version            : V1.0
 * Date               : 2021/03/09
 * Description        : adc采样示例,包括温度检测、单通道检测、差分通道检测、TouchKey检测、中断方式采样。
 *********************************************************************************
 * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
 * Attention: This software (modified or not) and binary are used for 
 * microcontroller manufactured by Nanjing Qinheng Microelectronics.
 *******************************************************************************/

#include "CH57x_common.h"

uint16_t adcBuff[40];

volatile uint8_t adclen;
volatile uint8_t DMA_end = 0;

/*********************************************************************
 * @fn      DebugInit
 *
 * @brief   调试初始化
 *
 * @return  none
 */
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();
}

/*********************************************************************
 * @fn      main
 *
 * @brief   主函数
 *
 * @return  none
 */
int main()
{
    uint8_t      i;
    signed short RoughCalib_Value = 0; // ADC粗调偏差值

    SetSysClock(CLK_SOURCE_PLL_60MHz);

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

    /* 温度采样并输出 */
    PRINT("\n1.Temperature sampling...\n");
    ADC_InterTSSampInit();
    for(i = 0; i < 20; i++)
    {
        adcBuff[i] = ADC_ExcutSingleConver(); // 连续采样20次
    }
    for(i = 0; i < 20; i++)
    {
        PRINT("%d \n", adc_to_temperature_celsius(adcBuff[i]));
    }

    /* 单通道采样:选择adc通道0做采样,对应 PA4引脚, 带数据校准功能 */
    PRINT("\n2.Single channel sampling...\n");
    GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_Floating);
    ADC_ExtSingleChSampInit(SampleFreq_3_2, ADC_PGA_0);

    RoughCalib_Value = ADC_DataCalib_Rough(); // 用于计算ADC内部偏差,记录到全局变量 RoughCalib_Value中
    PRINT("RoughCalib_Value =%d \n", RoughCalib_Value);

    ADC_ChannelCfg(0);
    for(i = 0; i < 20; i++)
    {
        adcBuff[i] = ADC_ExcutSingleConver() + RoughCalib_Value; // 连续采样20次
    }
    for(i = 0; i < 20; i++)
    {
        PRINT("%d \n", adcBuff[i]); // 注意:由于ADC内部偏差的存在,当采样电压在所选增益范围极限附近的时候,可能会出现数据溢出的现象
    }

    /* DMA单通道采样:选择adc通道0做采样,对应 PA4引脚 */
    PRINT("\n3.Single channel DMA sampling...\n");
    GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_Floating);
    ADC_ExtSingleChSampInit(SampleFreq_3_2, ADC_PGA_0);
    ADC_ChannelCfg(0);
    ADC_AutoConverCycle(192); // 采样周期为 (256-192)*16个系统时钟
    ADC_DMACfg(ENABLE, (uint16_t)(uint32_t)&adcBuff[0], (uint16_t)(uint32_t)&adcBuff[40], ADC_Mode_Single);
    PFIC_EnableIRQ(ADC_IRQn);
    ADC_StartDMA();
    while(!DMA_end);
    DMA_end = 0;
    ADC_DMACfg(DISABLE, 0, 0, 0);

    for(i = 0; i < 40; i++)
    {
        PRINT("%d \n", adcBuff[i]);
    }

    /* 差分通道采样:选择adc通道0做采样,对应 PA4(AIN0)、PA12(AIN2) */
    PRINT("\n4.Diff channel sampling...\n");
    GPIOA_ModeCfg(GPIO_Pin_4 | GPIO_Pin_12, GPIO_ModeIN_Floating);
    ADC_ExtDiffChSampInit(SampleFreq_3_2, ADC_PGA_0);
    ADC_ChannelCfg(0);
    for(i = 0; i < 20; i++)
    {
        adcBuff[i] = ADC_ExcutSingleConver(); // 连续采样20次
    }
    for(i = 0; i < 20; i++)
    {
        PRINT("%d \n", adcBuff[i]);
    }

    /* TouchKey采样:选择adc通道 2 做采样,对应 PA12 */
    PRINT("\n5.TouchKey sampling...\n");
    GPIOA_ModeCfg(GPIO_Pin_12, GPIO_ModeIN_Floating);
    TouchKey_ChSampInit();
    ADC_ChannelCfg(2);

    for(i = 0; i < 20; i++)
    {
        adcBuff[i] = TouchKey_ExcutSingleConver(0x10, 0); // 连续采样20次
    }
    for(i = 0; i < 20; i++)
    {
        PRINT("%d \n", adcBuff[i]);
    }

    /* 单通道采样:中断方式,选择adc通道1做采样,对应 PA5引脚, 不带数据校准功能 */
    PRINT("\n6.Single channel sampling in interrupt mode...\n");
    GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeIN_Floating);
    ADC_ExtSingleChSampInit(SampleFreq_3_2, ADC_PGA_0);
    ADC_ChannelCfg(1);
    adclen = 0;
    ADC_ClearITFlag();
    PFIC_EnableIRQ(ADC_IRQn);

    ADC_StartUp();
    while(adclen < 20);
    PFIC_DisableIRQ(ADC_IRQn);
    for(i = 0; i < 20; i++)
    {
        PRINT("%d \n", adcBuff[i]);
    }

    while(1);
}

/*********************************************************************
 * @fn      ADC_IRQHandler
 *
 * @brief   ADC中断函数
 *
 * @return  none
 */
__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode")))
void ADC_IRQHandler(void) //adc中断服务程序
{

    if(ADC_GetDMAStatus())
    {
        ADC_StopDMA();
        R16_ADC_DMA_BEG = ((uint32_t)adcBuff) & 0xffff;
        ADC_ClearDMAFlag();
        DMA_end = 1;
    }
    if(ADC_GetITStatus())
    {
        ADC_ClearITFlag();
        if(adclen < 20)
        {
            adcBuff[adclen] = ADC_ReadConverValue();
            ADC_StartUp(); // 作用清除中断标志并开启新一轮采样
        }
        adclen++;
    }
}

(八) SPI

#include "CH57x_common.h"

__attribute__((aligned(4))) uint8_t spiBuff[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6};
__attribute__((aligned(4))) uint8_t spiBuffrev[16];

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();
}

int main()
{
    uint8_t i;

    SetSysClock(CLK_SOURCE_PLL_60MHz);

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

#if 1
    /* 主机模式 */
    PRINT("1.spi0 mul master mode send data ...\n");
    DelayMs(100);

    GPIOA_SetBits(GPIO_Pin_12);
    GPIOA_ModeCfg(GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14, GPIO_ModeOut_PP_5mA);
    SPI0_MasterDefInit();

    // 单字节发送
    GPIOA_ResetBits(GPIO_Pin_12);
    SPI0_MasterSendByte(0x55);
    GPIOA_SetBits(GPIO_Pin_12);
    DelayMs(1);
    GPIOA_ResetBits(GPIO_Pin_12);
    i = SPI0_MasterRecvByte();
    GPIOA_SetBits(GPIO_Pin_12);
    DelayMs(2);

    // FIFO 连续发送
    GPIOA_ResetBits(GPIO_Pin_12);
    SPI0_MasterTrans(spiBuff, 9);
    GPIOA_SetBits(GPIO_Pin_12);
    DelayMs(1);
    GPIOA_ResetBits(GPIO_Pin_12);
    SPI0_MasterRecv(spiBuffrev, 12);
    GPIOA_SetBits(GPIO_Pin_12);
    DelayMs(1);

    // DMA 连续发送
    GPIOA_ResetBits(GPIO_Pin_12);
    SPI0_MasterDMATrans(spiBuff, 12);
    GPIOA_SetBits(GPIO_Pin_12);
    DelayMs(1);
    GPIOA_ResetBits(GPIO_Pin_12);
    SPI0_MasterDMARecv(spiBuffrev, 12);
    GPIOA_SetBits(GPIO_Pin_12);

    PRINT("END ...\n");
    while(1);
#endif

#if 0
    /* 设备模式 */
    PRINT("1.spi0 mul slave mode \n");
    GPIOA_ModeCfg(GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15, GPIO_ModeIN_PU);
    SPI0_SlaveInit();
    i = SPI0_SlaveRecvByte();
    SPI0_SlaveSendByte(~i);

    SPI0_SlaveRecv(spiBuffrev, 9);
    SPI0_SlaveTrans(spiBuffrev, 12);
    SPI0_SlaveDMARecv(spiBuffrev, 12);
    SPI0_SlaveDMATrans(spiBuffrev, 12);

    while(1);
#endif

    while(1);
}

WCH
License:  CC BY 4.0
Share

Further Reading

OLDER

ESP32(二) ADC

NEWER

CH573(二) 蓝牙

Recently Updated

  • ESP32(八) 简单的webserver
  • ESP32(七) NVS
  • ESP32(四) STA & AP
  • 多级菜单
  • ESP32(五) ESP32 OTA

Trending Tags

WCH Linux Elec freeRTOS STM ESP Flutter Others SwiftUI

Contents

©2025 松果工作室. Some rights reserved.

Using the Halo theme Chirpy