CW32

前言 

电池备份(VBAT)功能的实现方法,一般是使用 MCU 自带的 VBAT 引脚,通过在该引脚连接钮扣电池,当系统电源因故掉电时,保持 MCU 内部备份寄存器内容和 RTC 时间信息不会丢失。 

本文档介绍了如何基于 CW32 系列 MCU,通过增加简单的外部电路配合软件实现 VBAT 功能,在系统电源掉 电后仍能保持 RTC 时钟正常计时,以及如何降低系统功耗,从而延长后备电池的使用寿命。

1 、电路设计 

对于自带 VBAT 引脚的 MCU,MCU 内部有对 VBAT 电源和系统电源的管理单元,保证在系统电源掉电后,及 时切换 VBAT 引脚电源给备份域供电,保证 RTC 正常工作。 

对于没有 VBAT引脚的 CW32,要实现类似的功能,可以在外部进行后备带电池和系统电源的切换,如下图所示:

1.png

后备电池(B1)提供的备用电源 VBAT 和系统电源 VDDIN 通过 2 个肖特基二极管(D1)合路,合路后的 电源 VDD 给 MCU 的数字域 DVCC 和模拟域 AVCC 进行供电。系统电源 VDDIN 通过 R3、R4 电阻分压得到 WAKEIO 信号,连接到 MCU 的 IO 引脚。注意遵循如下规则:

 1. Vwakeio 要大于 MCU IO 口的 Vih;

 2. VDDIN 必须高于 Vb1 在 0.4V 以上,否则如果 VDDIN 和 Vb1 相等,在系统电源正常时,后备电池也会有一定 的泄放电流,不利于节省后备电池电量。

2 、程序设计 

程序启动后正常初始化时钟、IO、RTC 以及 OELD,循环中检测系统电源是否存在,如存在则读取 RTC 时间 并显示。 

当系统电源 VDDIN 因故掉电,则关闭 OLED 电源,并进入 DeepSleep 低功耗睡眠模式。 

当系统电源 VDDIN 恢复供电时,产生高电平中断,唤醒 MCU,退出 DeepSleep 低功耗睡眠模式。

3 、参考代码

int32_t main(void)
{
    RCC_Configuration();     // 时钟配置
    GPIO_Configuration();     //GPIO配置
    OLED_Init();          //OLED显示屏初始化配置
    dis_err("RTC_TestBoard");   // 显示
    FirmwareDelay(5000000);   // 增加延时防止过早休眠影响程序烧写
    RTC_init();          //RTC时钟初始化
    //DeepSleep 唤醒时,保持原系统时钟来源
    RCC_WAKEUPCLK_Config(RCC_SYSCTRL_WAKEUPCLKDIS);
    ShowTime();       // 获取时间数据
    displaydatetime();    // 显示当前时间
    while(1)
    {
        if( 0==PB05_GETVALUE() )  // 循环检测是否掉电
        {
            PA05_SETHIGH();   // 关 OLED 电源
            SCB->SCR = 0X04;  //DeepSleep
            __WFI();       //MCU 进入DeepSleep模式以节省功耗
            OLED_Init();     // 外部电源接入后唤醒,重新初始化 OLED
        }
        else
        {
            ShowTime();      // 获取时间数据
            displaydatetime();   // 显示当前时间
        }
    }
}

void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStruct= {0};
    __RCC_GPIOB_CLK_ENABLE();         // 开 
    GPIOB 时钟GPIO_InitStruct.IT  = GPIO_IT_RISING;    // 使能上升沿中断
    GPIO_InitStruct.Mode  = GPIO_MODE_INPUT;  // 输入模式
    GPIO_InitStruct.Pins = GPIO_PIN_5 ;    //PB05,连接 WAKEIO 网络
    GPIO_Init(CW_GPIOB, &GPIO_InitStruct);  // 初始化 IO
    GPIOB_INTFLAG_CLR(bv5);        // 清除 PB05 中断标志
    NVIC_EnableIRQ(GPIOB_IRQn);      // 使能 PB05 中断
}

4 、实际测试

使用 CW32L031C8T6 设计了用于测试后备电池功能的评估板,实物如下图所示:

2.png

使用 3V 的 CR2032 钮扣电池,实测电池电压为 3.14V;VDDIN 使用可调节数字电源,设置为 3.54V,保证 VDDIN >= Vb1 + 0.4V;D1 实测合路后的电源电压为 3.21V。

3.png

4.1 测试数据 

实际测试时,断开 J4 跳线接入万用表,设置万用表为电流测试档位。 

1. 关闭 VDDIN 电源输入,MCU 检测到无外电输入,关闭 OLED 显示,进入 DeepSleep 模式,实测此时 B1 电流为 +0.95μA。 

2. 打开 VDDIN电源输入,MCU被高电平中断从 DeepSleep状态唤醒到正常状态,OLED正常显示当前时间, 实测此时 B1 电流为 -75nA(负电流是因为 D1 处于反向偏置状态,有小的反向漏电流)。 

测试结果符合电路设计预期,以 CR2032 电池容量为 200mAH 计算,则电池可用时间为 210526 小时,合计 24 年(不考虑电池和产品寿命),可实现超长待机时间,完全满足各种低功耗产品对 RTC 后备电池容量需求。

5 、附件 

5.1 RTC_TestBoard 单板原理图

4.png

5.png

来源:武汉芯源半导体

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 93

1.PID温控系统是一种常用的控制系统,用于实现对温度变量的精确控制。PID算法根据当前的温度误差以及误差的变化率,计算一个控制信号,用于调节加热器的输出。以下是PID算法的三个主要组成部分:

①比例(Proportional)控制:比例控制是根据当前的温度误差来计算控制信号。具体而言,通过将设定温度与实际温度之间的差异称为误差,然后将误差乘以一个比例增益参数,得到一个修正值。这个修正值与控制设备的输出信号相加,以调整温度控制。

②积分(Integral)控制:积分控制用于处理长期的温度误差。它通过对温度误差进行积分来计算一个积分误差。积分误差乘以积分增益参数,并且在一段时间内进行积累,得到一个修正值。积分控制可以帮助消除持续的稳态误差,使系统更快地达到设定温度。

③微分(Derivative)控制:微分控制用于处理温度变化的速率。它通过计算温度误差的变化率,即误差的导数,得到一个微分值。微分值乘以一个微分增益参数,用于调整修正值。微分控制可以帮助系统更快地响应温度变化,以防止过冲。

通过结合比例、积分和微分部分的修正值,PID控制算法可以计算出最终的控制信号。这个控制信号会被传递给加热器,以控制温度的变化。

2.本实验用到了CW32-48大学计划开发板OK、温控实验模块及Keil5开发环境。


1.png

CW32-48大学计划开发板OK   

2.png

温控实验模块   

3.png 

4.png

温控模块电路原理图

3.PID控制算法的具体原理可参考以下链接中的文章

1)https://zhuanlan.zhihu.com/p/39573490

2)https://zhuanlan.zhihu.com/p/3473726243)https://zhuanlan.zhihu.com/p/41962512
利用热敏电阻采集温度的原理及方法可参考往期文章及视频。

4.核心代码

mian.c:

#include "config.h"

unsigned char face = 0;       //界面变量
unsigned char face_brush = 0; //界面刷新频率控制

void InitSystem(void)  
{  
    RCC_Configuration();        //时钟配置  
    ADC_Configuration();        //ADC采集通道配置,采集NTC热敏电阻电压  
    PID_Configuration();        //PID参数配置  
    GPIO_KEYS_Configuration(); //按键GPIO配置  
    PWM_Init();                  //两路PWM输出初始化  
    Lcd_Init();                 //TFT屏幕初始化  
    BTIM_Init();                //定时器初始化}

void Interface(void)  //人机交互界面
{  
    if ( face_brush > 200 )  //200ms刷新一次  
    {    
        face_brush = 0;    
        switch(face)    
        {      
            case 0://显示PV和SV,该界面下,可以设定SV        
            TFTSHOW_STRING_HEADLINE(0,0,"  PID  Control  ");        
            TFTSHOW_STRING(2,0,"REAL_Temper(℃):");        
            TFTSHOW_STRING(4,0,"   P V:       ");        
            TFTSHOW_FLOAT_NUMBER(4,8,pid.Pv);        
            TFTSHOW_STRING(6,0,"SET_Temper(℃):");        
            TFTSHOW_STRING(8,0,"   S V:       ");        
            TFTSHOW_FLOAT_NUMBER(8,8,pid.set_Sv);        
            break;      
            case 1://该界面下,可以设定P参数        
            TFTSHOW_STRING_HEADLINE(0,0,"  PID  Control  ");        
            TFTSHOW_STRING(2,0,"SET PID Control:");        
            TFTSHOW_STRING(4,0,"    P :       ");        
            TFTSHOW_INT_NUMBER(4,8,pid.set_Kp);        
            break;      
            case 2://该界面下,可以设定I参数        
            TFTSHOW_STRING_HEADLINE(0,0,"  PID  Control  ");        
            TFTSHOW_STRING(2,0,"SET PID Control:");        
            TFTSHOW_STRING(4,0,"    I :       ");        
            TFTSHOW_FLOAT_NUMBER(4,8,pid.set_Ki);        
            break;      
            case 3://该界面下,可以设定D参数        
            TFTSHOW_STRING_HEADLINE(0,0,"  PID  Control  ");        
            TFTSHOW_STRING(2,0,"SET PID Control:");        
            TFTSHOW_STRING(4,0,"    D :       ");        
            TFTSHOW_INT_NUMBER(4,8,pid.set_Kd);        
            break;      
            case 4://该界面下,可以设定Out0,即修正值        
            TFTSHOW_STRING_HEADLINE(0,0,"  PID  Control  ");        
            TFTSHOW_STRING(2,0,"SET PID Control:");        
            TFTSHOW_STRING(4,0,"   OUT0 :      ");        
            TFTSHOW_INT_NUMBER(4,10,pid.set_Out0);        
            break;    
        }  
    }
}

int main()           //主函数
{  
    InitSystem();      //系统初始化  
    while(1)  
    {    
        PID_Calc();      //PID运算    
        Interface();     //人机交互界面    
        Keys_Function(); //按键控制      
    }
}

pwm.c:

#include "pwm.h"

void PWM_Init(void)
{  
   RCC_APBPeriphClk_Enable1(RCC_APB1_PERIPH_GTIM2,ENABLE); //使能GTIM2时钟
    
   __RCC_GPIOA_CLK_ENABLE();   //使能GPIOA时钟
  
   PA01_AFx_GTIM2CH2();        //打开PWM输出通道  
   PA02_AFx_GTIM2CH3();
  
   GPIO_InitTypeDef GPIO_InitStruct;
  
   GPIO_InitStruct.IT = GPIO_IT_NONE;   
   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;  //推挽输出模式  
   GPIO_InitStruct.Pins = GPIO_PIN_1|GPIO_PIN_2;  
   GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;  
   GPIO_Init(CW_GPIOA, &GPIO_InitStruct);
  
   GTIM_InitTypeDef GTIM_Initstructure;     //通用定时器  
   GTIM_Initstructure.Mode=GTIM_MODE_TIME;  //计数模式  
   GTIM_Initstructure.OneShotMode=GTIM_COUNT_CONTINUE; //连续计数  
   GTIM_Initstructure.Prescaler=GTIM_PRESCALER_DIV64; //预分频  
   GTIM_Initstructure.ReloadValue=2000-1; //ARR,计数重载周期2000  
   GTIM_Initstructure.ToggleOutState=DISABLE;  
   GTIM_TimeBaseInit(CW_GTIM2,&GTIM_Initstructure);
  
   GTIM_OCInit(CW_GTIM2,GTIM_CHANNEL3,GTIM_OC_OUTPUT_PWM_LOW); //GTIM2输出比较,CH3、CH2  
   GTIM_OCInit(CW_GTIM2,GTIM_CHANNEL2,GTIM_OC_OUTPUT_PWM_LOW); //有效占空比为低电平  
   GTIM_Cmd(CW_GTIM2,ENABLE); //使能GTIM2
}

void PWM1_Output(uint32_t value)
{  
   GTIM_SetCompare3(CW_GTIM2,value);  //设置GTIM2通道3的CCR
}

void PWM2_Output(uint32_t value)
{  
   GTIM_SetCompare2(CW_GTIM2,value);  //设置GTIM2通道2的CCR
}

void PWM_ALL_Output(uint32_t value)  //PWM1、2同步输出
{  
      PWM1_Output(value);  
      PWM2_Output(value);
}

pid.c:

#include "pid.h"

PID pid;    //定义PID结构体变量pid

void PID_Configuration(void)   //PID参数初始化配置 
{  
    pid.Sv     = 55;
    
  pid.Kp     = 350;  //比例系数  
  pid.Ki     = 10;   //积分系数  
  pid.Kd     = 38;   //微分系数
  
  pid.Ek_1   = 0;    //上一次偏差  
  pid.T      = 400;  //PID计算周期
  
  pid.cnt    = 0;      
  pid.cycle  = 2000; //PWM周期  
  pid.Out0   = 500;  //PID修正值
  
  pid.set_Sv = pid.Sv;  
  pid.set_Kp = pid.Kp;  
  pid.set_Ki = pid.Ki;  
  pid.set_Kd = pid.Kd;  
  pid.set_Out0 = pid.Out0;
}

float Get_Pv(void)  //Pv意为当前测量值,即当前温度
{  
    return Get_Temperture();
}

void PID_Calc(void)    //PID算法
{  
    float Pout,Iout,Dout;  
    float out;
  
  if ( pid.cnt > pid.T )   //控制计算周期  
  {    
      pid.cnt = 0;
    
    pid.Pv = Get_Pv();           
    pid.Ek = pid.Sv - pid.Pv; //计算偏差    
    pid.SumEk += pid.Ek;  //偏差累积

    
    Pout = pid.Kp * pid.Ek;  //比例控制
    
    Dout = pid.Kd * (pid.Ek - pid.Ek_1);  //微分控制
    
    if(pid.Pv>(pid.Sv-1))   //当测量值非常接近目标值的时候加入积分控制    
    {      
        Iout = pid.Ki * pid.SumEk;           //积分控制      
        out = Pout + Iout + Dout + pid.Out0;     
    }    
    else   out  = Pout + Dout + pid.Out0;  //测量值距离目标值较远时只使用PD控制
    
    if ( out > pid.cycle ) pid.Out = pid.cycle; //限幅    
    else if ( out < 0 )    pid.Out = 0;    
    else                   pid.Out = out;    
    PWM_ALL_Output(pid.Out);  //控制PWM输出    
    pid.Ek_1 = pid.Ek;  //进行下一次PID运算之前,将本次偏差变为上次偏差  
   }
}

5.实验最终现象

5.png

来源:CW32生态社区

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 45

描述

简介:基于武汉芯源半导体CW32F030C8T6和启英泰伦CI-C22GS02制作的智能语音分类垃圾桶,能够实现识别语音来判断垃圾种类,同时打开相应的垃圾桶,可外接普通按键或者触摸按键,也可以外接红外接近传感器来打开对应的垃圾桶。

项目说明

1.jpg

2.jpg

3.jpg

本次设计采用武汉芯源半导体的CW32F030C8T6作为主控,主要负责和离线语音模块的串口通讯,负责输出4路PWM信号、驱动IPS显示屏、控制2路MOS驱动电路(控制风扇和灯光)、驱动4个WS2812B灯。语音识模块采用启英泰伦CI-C22GS02模块(主芯片采用Cl1122,支持本地200条命令词以下的离线语音识别),主要负责语音识别和播报语音,可通过串口与MCU通讯。

项目相关功能介绍介绍

1.离线语音模块的命令词可自行定制,最多可录入200个命令词,目前已录入了168条垃圾名词和一些控制指令。当语音模块识别到正确的命令词后,串口输出规定协议的数据。语音模块也可以接收规定协议的串口数据来播报指定的语音。离线语音模块的串口1和MCU主控的串口2使用跳线连接,方便分别开发调试。

4.jpg

5.jpg

2.主控输出4路PWM信号(周期20us,频率50Hz),可直接驱动4路舵机。

6.jpg

3.四个WS2812B灯作为4类垃圾的指示灯,语音模块在识别到正确的语音后,由CW32主控来控制指定的灯点亮对应的颜色。

7.jpg

4.电路采用直流12V供电,经DC-DC降压后输出5.2V,5.2V再经LDO降压后输出3.3V。其中CI-C22GS02模块、舵机、WS2812B、外部灯光和风扇供电均采用5.2V供电,MCU主控、IPS显示屏采用3.3V供电。

8.jpg

5.电路设计了2路MOS驱动电路,可外接5V的小风扇和5V供电的灯。另外预留了2种屏幕接口,支持8针的SPI接口的屏幕或者4针的I2C接口的屏幕。预留3组扩展接口,将剩余的IO口全部引出,方便扩展。

9.jpg

10.jpg

硬件部分介绍

智能语音分类垃圾桶主要包含主控板、显示屏、独立按键模块、加装舵机的垃圾桶模型、12V电源适配器。

软件部分介绍

软件分两部分,一部分是针对CW32F030C8T6的程序开发,另一部分是针对CI-C22GS02离线语音模块的命令词、语言模型、声学模型以及固件的制作。

1. CW32F030C8T6的程序开发。采用Keil5开发,借鉴了CW32官方例程和开源平台上一些大佬的程序。程序中涉及GPIO、DMA、定时器、ADC、UART、PWM、SPI等功能的实现。

因本人水平有限,写的程序只能说能用,但不保证好用。里面使用了大量的全局变量,还有很多改进的地方。

下面展示了部分程序。

(1)主程序

11.jpg

12.jpg

(2)串口发送程序

13.jpg

(3)串口接收程序(有BUG,接收两遍才能接收完整)

14.jpg15.jpg

(4)舵机执行动作的程序

采用定时器和标志位,使舵机缓慢打开,一定时间后缓慢自动关闭,4路舵机相互不受影响。

16.jpg

2. CI-C22GS02离线语音模块的命令词、语言模型、声学模型以及固件的制作。具体制作教程建议参考启英泰伦文档中心

(1)命令词列表(根据自己需要定制)

17.jpg

(2)生成的语言模型相应的文件放在这里

18.jpg

19.jpg

(3)生成的声学模型相应的文件放在这里

20.jpg

(4)生成固件之前需要手动修改这里,这里按照数字顺序(16进制)来修改。

21.jpg

(5)合并烧录固件

22.jpg

(6)打包固件

23.jpg

 24.jpg

(7)烧录固件。使用CH340串口工具,CH340的TX接语音模块串口0的RXD,CH340的RX接语音模块串口0的TXD,GNG接GND。CH340先插入电脑,烧录软件中出现对应的串口后,在右边的方框中打勾,然后按住UPDATE 按钮,CH340D的5V接语音模块+5V,此时烧录软件会显示开始烧录,直到烧录完成。

25.jpg

26.jpg

固件烧录成功后,喇叭应该会播报事先录入的欢迎词,这就说明烧录成功。

视频地址:https://www.bilibili.com/video/BV1oh411w7x2/?vd_source=2462ee6bfbc931195...

设计图

27.jpg

原理图_V1.0

28.jpg

原理图_V2.0

29.jpg

PCB_V2.0

工程源文件链接:https://oshwhub.com/myself1820/zhi-neng-yu-yin-fen-lei-de-la-ji-tong

来源:CW32生态社区

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com

围观 29

无刷电机是一种新型的电机,其特点是不需要刷子进行转子与定子的电接触。相比于传统电机,无刷电机具有更高的效率、更小的体积和更长的寿命。本文将从工作原理、组成结构和与传统电机的区别三个方面来详细介绍无刷电机的特点。

1.png

2.png

图1 网上的无刷电机

首先,无刷电机的工作原理是基于电磁感应和电子控制。无刷电机的转子是由永磁体组成,定子则是由线圈组成。当电流通过定子线圈时,会产生一个磁场,这个磁场会与转子永磁体的磁场相互作用,从而使转子开始旋转。在转子旋转的同时,电子控制器会监测转子的位置和速度,并控制定子线圈的电流,从而保证电机的稳定运行。

其次,无刷电机的组成结构也有所不同。传统电机的转子是由电刷和电极组成,而无刷电机的转子则是由永磁体和磁传感器组成。此外,无刷电机还需要电子控制器来控制电流和转子的位置和速度。这些特殊的组成结构使得无刷电机具有更高的效率和更长的寿命。

最后,无刷电机与传统电机的区别在于其效率、体积和寿命。无刷电机的效率比传统电机高出约10%至20%,这是由于无刷电机不需要电刷进行转子与定子的电接触,从而减少了摩擦和能量损失。此外,无刷电机的体积也比传统电机小,这是由于无刷电机的转子不需要电刷,从而减少了转子的体积。最后,无刷电机的寿命也比传统电机长,这是由于无刷电机不需要电刷进行电接触,从而减少了电刷的磨损和寿命。

3.png

图2 无刷直流电机结构示意图

综上所述,无刷电机具有高效、小巧和长寿命等特点。随着无刷电机技术的不断发展,无刷电机将在越来越多的领域得到应用,如电动汽车、无人机、机器人等。

所以在各个行业运用无刷电机会越来越多,本次会用基于CW32芯片之下开发一款可以应用于大多数场景的一款水泵。现在对于水泵要求越来越高,所以我们改进水泵的工作模式,使水泵工作于最优工作点,降低功耗,就能实现水泵系统的节能,即节约电能和水能,给企业带来效益,同时也能提升竞争力。

在系统中,水泵的运行是靠无刷直流电机来带动的。本课题研究的目的是设计一套基于 CW32 的无位置传感器无刷直流电机控制系统(方波控制模式),既可以改进水泵的工作模式,使水泵工作点最优;又可以使水泵电机结构简单,控制方式更为灵活。以此将整个系统加入各个不同场景中,让CW32低功耗的优点,能让水泵共更加节能,高效。

本文设计一个小型水泵循环控制系统,该系统中带动水泵运行的电机的额定电压是48V,额定功率为500W。控制系统是基于CW32处理器,采用反电势过零检测方法对转子位置进行检测,从而实现对电机的换向控制。水泵控制系统中,采用无位置传感器无刷直流电机来带动水泵运行,不但缩小了水泵体积,而且增强了水泵运行时电机的抗干扰性和稳定可靠性。使水泵工作于最优工作点,尽可能使运行功率降低,改变了水泵一直满功率运行的状况,降低了功耗,实现了水泵系统的节能。

来源:CW32生态社区

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 60

资料链接如下:

BD网盘链接:

https://pan.baidu.com/s/1IsFqi-bdPQcilu71JMrsVA 

提取码:n99y

1. DS1302是一款集成了实时时钟(RTC)功能的芯片。RTC是一种能够精确测量和跟踪时间的电子设备,可以提供准确的日期和时间信息。DS1302实时时钟芯片由Maxim Integrated(美信半导体)生产,具有以下主要特点:

①时钟精度:DS1302采用32.768kHz的晶体振荡器来提供基准时钟信号。它具有较高的时钟精度,使得它可以提供准确的时间信息,每月的时间偏差非常小。

②时钟和日历功能:DS1302可以跟踪秒、分钟、小时、日期、月份和年份。它提供了完整的时钟和日历功能,可以准确地记录时间和日期。

③低功耗设计:DS1302芯片采用了低功耗设计,因此在电池供电时可以提供长时间的运行时间。

④数据保持功能:DS1302具有数据保持功能,使得即使在电源断电的情况下,时钟和日历数据仍然可以得到保持,确保数据的可靠性和连续性。

⑤简化的接口:DS1302通过串行接口(2线或3线),与微控制器或其他外部设备进行通信。这种简化的接口使得它更容易与其他系统集成,实现实时时钟功能。

DS1302实时时钟芯片被广泛应用于各种应用领域,如电子设备、仪器仪表、自动化系统、安防系统等需要准确时间信息的场合。它的易用性、低功耗以及稳定的性能使得它成为常用的实时时钟解决方案之一。

2.本实验用到了CW32 Cortex-M实训套件实验箱、DS1302实时时钟模块及Keil5开发环境。

1.png

CW32 Cortex-M实训套件

2.png

DS1302实时时钟模块实物

3.png

DS1302原理图

3.DS1302具体工作原理可观看视频,或参考以下链接中的文章

https://blog.csdn.net/u013184273/article/details/78843881

4.核心代码

/*
用TFT屏幕显示年、月、日、星期、时、分、秒
显示界面如下:
----------------
DS1302 Real Time 

Year :xxxx
Month:xx
Day  :xx
Week :xx
xx:xx:xx

----------------
*/

#include "main.h"
#include "config.h"
#include "Ds1302.h"        //DS1302底层驱动代码
#include "Lcd_Driver.h"
#include "LCD_calculate.h"

char strings[2];         //储存要显示的数字

int main()
{  
    u8 value = 0;   
    
    RCC_Configuration(); //配置时钟   
    
    Lcd_Init();  
    Lcd_Clear(GRAY0);   
    
    Ds1302_GPIO_Init();  //GPIO配置 
    
    //  Ds1302_Config(23,7,7,5,14,58,55); //初始化DS1302,2023年7月7日星期五23点59分55秒   

    Gui_DrawFont_GBK16(0,0,WHITE,RED,"DS1302 Real Time"); //显示界面  
    Gui_DrawFont_GBK16(0,32,WHITE,RED,"Year :20  ");  
    Gui_DrawFont_GBK16(0,48,WHITE,RED,"Month:    ");  
    Gui_DrawFont_GBK16(0,64,WHITE,RED,"Day  :    ");  
    Gui_DrawFont_GBK16(0,80,WHITE,RED,"Week :    ");  
    Gui_DrawFont_GBK16(0,96,WHITE,RED,"  :  :    ");   

    while(1)  
    {        
        Ds1302_GetHour(&value);                  //小时    
        sprintf(strings,"%d",value/10);    
        Gui_DrawFont_GBK16(0,96,WHITE,RED,strings);    
        sprintf(strings,"%d",value%10);    
        Gui_DrawFont_GBK16(8,96,WHITE,RED,strings);     
    
        Ds1302_GetMinite(&value);                //分钟    
        sprintf(strings,"%d",value/10);    
        Gui_DrawFont_GBK16(24,96,WHITE,RED,strings);    
        sprintf(strings,"%d",value%10);    
        Gui_DrawFont_GBK16(32,96,WHITE,RED,strings);     
        
        Ds1302_GetSecond(&value);                //秒钟    
        sprintf(strings,"%d",value/10);    
        Gui_DrawFont_GBK16(48,96,WHITE,RED,strings);    
        sprintf(strings,"%d",value%10);    
        Gui_DrawFont_GBK16(56,96,WHITE,RED,strings);       
    
        Ds1302_GetDay(&value);                  //星期    
        sprintf(strings,"%d",value/10);    
        Gui_DrawFont_GBK16(40+8,80,WHITE,RED,strings);    
        sprintf(strings,"%d",value%10);    
        Gui_DrawFont_GBK16(48+8,80,WHITE,RED,strings);     
    
        Ds1302_GetDate(&value);                 //日期    
        sprintf(strings,"%d",value/10);    
        Gui_DrawFont_GBK16(32+16,64,WHITE,RED,strings);    
        sprintf(strings,"%d",value%10);    
        Gui_DrawFont_GBK16(40+16,64,WHITE,RED,strings);    
       
        Ds1302_GetMonth(&value);                //月份    
        sprintf(strings,"%d",value/10);    
        Gui_DrawFont_GBK16(48,48,WHITE,RED,strings);    
        sprintf(strings,"%d",value%10);    
        Gui_DrawFont_GBK16(55,48,WHITE,RED,strings);     
    
        Ds1302_GetYear(&value);                 //年份    
        sprintf(strings,"%d",value/10);    
        Gui_DrawFont_GBK16(56+8,32,WHITE,RED,strings);    
        sprintf(strings,"%d",value%10);    
        Gui_DrawFont_GBK16(64+8,32,WHITE,RED,strings);  
    }
}

5.实验最终现象

把程序下载进DS1302模块,DS1302经过程序初始化后将开始计时。

4.png

实验箱接线 

5.png

显示时间   

 6.png

断电30s重新上电  

来源:CW32生态社区

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 8

1.利用NTC热敏电阻来采集温度具有高灵敏度、快速响应、宽温度测量范围和成本效益高等优势,这使得它成为许多应用中常用的温度传感器之一。

本期视频就来讲解基于CW32热敏电阻采集温度的应用。

资料链接如下:

BD网盘链接:

https://pan.baidu.com/s/1BBQ_7AmfirJPsXr2zxaOJw

提取码:6bc3

2.本实验用到了CW32 Cortex-M实训套件实验箱、NTC热敏电阻及Keil5开发环境。

1.png

CW32 Cortex-M实训套件

2.png

NTC热敏电阻实物

3.png

热敏电阻原理图

4.png

热敏电阻主要技术参数

5.png

6.png

7.png

3.NTC具体原理可观看视频,或参考以下链接中的文章

https://zhuanlan.zhihu.com/p/179181715

4.核心代码

/*

用TFT屏幕显示

1.热敏电阻的阻值

2.转换得到的温度

显示界面如下

-----------------------        
    NTC
  R:****   
  Tempture:****
-----------------------
*/

#include "main.h"
#include "table.h"   //阻温表
#include "config.h"
#include "LCD_calculate.h"
#include "Lcd_Driver.h"

char temp[10];  
unsigned char cnt = 0;
float dat_AD = 0;  //ADC采集电压
int R = 0;  //电阻值
float tempture = 0; //温度

void ADC_Configuration(void); // ADC初始化配置
float Get_ADC(void);  //采集电压值

int main()
{    
   unsigned char max,min,mid;    
   unsigned  int temp;  
   char strings[10];
  
  RCC_Configuration(); //时钟配置  A
  DC_Configuration(); //ADC配置
  
  Lcd_Init();          //TFT屏初始化配置  
  Lcd_Clear(GRAY0);    //清屏操作
  
  Gui_DrawFont_GBK16(0,0,WHITE,RED,"       NTC      "); //第一行:ADC TEST:  
  Gui_DrawFont_GBK16(0,32,WHITE,RED,"R:");             //第二行:R:  
  Gui_DrawFont_GBK16(0,48,WHITE,RED,"Temperature:"); //第三行:Temperature:
  
  while(1)  
  {        
     dat_AD = Get_ADC()*3.3/4095;  //单片机的参考电压为3.3V,12位的ADC    
     R = dat_AD*10000/(5-dat_AD);//VCC接5V,测得VCC实际电压值为4.58V,更为精准
    
    max = 97;  //温度上限97    
    min = 0;   //温度下限0
    
    while(1)   //二分查找法    
    {      
        mid = ( max + min ) / 2;      
        if( Table[mid] < R ) max = mid;      
        else min = mid;      
        if( (max-min) <= 1 ) break;    
    }
    
    if ( max == min ) tempture = min * 10;    
    else    
    {      
        temp = ( Table[min] - Table[max] ) / 10;  //计算温度的小数部分      
        temp = ( Table[min] - R ) / temp;           
        tempture = temp;       
        tempture = 10 * min + tempture;  //扩大十倍,方便计算    
    }    
    tempture /= 10;
    
    sprintf(strings,"%d",R);  //TFT显示阻值    
    Gui_DrawFont_GBK16(16,32,WHITE,RED,strings);    
    Gui_DrawFont_GBK16(48,32,WHITE,RED,"          ");
    
    sprintf(strings,"%.1f",tempture);    
    Gui_DrawFont_GBK16(96,48,WHITE,RED,strings); //TFT显示温度
    
    delay_ms(500);  
    }
}
float Get_ADC() //ADC采集
{  
   unsigned int temp_dat_adc = 0;
  ADC_SoftwareStartConvCmd(ENABLE);  
  while(ADC_GetITStatus(ADC_IT_EOC))  
  {    
      ADC_ClearITPendingBit(ADC_IT_EOC);          
      temp_dat_adc=ADC_GetConversionValue();        
  }  
  return   (float)temp_dat_adc;
}

5.实验最终现象

8.png

实验接线箱

9.jpg

来源:CW32生态社区

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 31

前言 

CW32 电容式触摸按键设计指南向客户提供一种利用 CW32 内部资源结合软件编程实现电容式触摸按键有效 触摸检测的方法。本指南的内容重点在于工作原理、软件检测过程以及调试指引。 

利用芯源半导体的 CW32 系列小规模 MCU 的 IO、比较器、定时器、高速高精度内置 RC 时钟源以及高算力 等功能,通过检测电路端子电容的微小变化和波动,实现电容式触摸按键功能。其外围电路简单,占用资源 比例不高,非常有利于用户在节约 BOM 成本的前提下拓展功能。结合适当的工业化设计,触摸按键比接触 式按键更美观、耐磨的同时,还具有防水、抗干扰、寿命长等多种优势。 

通过本文,您会了解到如何利用内置电压比较器和内置定时器及软件配合,实现灵活方便的按键检测。本文 在介绍标准演示板(如下图)和演示软件的性能参数的同时,还会给出详细的调试建议以及设计参数选择倾 向分析,用以帮助客户快速而自信地完成设计并实施调试。

1.png

1、 电容触摸检测基本原理

独立于电路的金属部件都能够作为电容触摸传感器使用,其原理在于金属部件附近存在手指时,相当于增加 了金属部件对地的旁路电容。因此,利用 CW32 系列 MCU 的 IO 口对金属部件充电,并检测电容放电时间的 变化,理论上能够辨别金属部件附近是否存在手指按压动作。当无手指存在时,金属部件的电容为 Cp,其放 电时间为 t1;当存在手指时,增加的旁路电容为 Cx,此时的放电时间为 t2,如下图所示,可以看出两者之间 的放电时间是不一样的:

2.png

2、 基于 CW32F003 的触摸按键方案简介

由于 CW32F003 集成了电压比较器 VC 和定时器,因此触摸按键方案可以通过软件来实现,其实现的原来框 图如下所示:

3.png

其过程如下:

1. GTIM 配置为门控计数方式,计数源为芯片内部的 PCLK 时钟。 

2. VC 比较器的同相端配置为按键的接口,反相段配置为参考,参考的来源为芯片的 VCC 通过内部电阻网 络分压得到,VC 比较器输出极性不反转。

3. GPIO 口配置为数字输出,输出高电平对电容充电。由于电容容值比较小,充电电流较大(图中红色箭 头所示),电容上的电压很快达到 VCC。

4. GTIM的计数器 CNT清 0,GPIO口配置为输入高阻态,电容上的电荷基本通过 R泄放(图中蓝色箭头所示), 需要一定的时间,此时电容上的电压要比 VC 比较器的反相端的电压高,VC 输出高电平,是 GTIM 的门 控信号有效,GTIM 进行计数。 

5. 当电容上的电压降低到比 VC 比较器的反相端的参考电压低时,VC 输出低电平,GTIM 停止计数,同时 VC 比较将产生一个中断信号,此时读取 GTIM 的 CNT 的计数值,和判决门限比较可以判断是否发生触 摸按键的事件。如下图所示:

4.png

3、 电容触摸检测电路软件过程

在范例程序中,软件定时(用定时器中断实现)对每个被测 IO 充电并检测放电时间 N 次,N 次循环检测后, 将统计结果提交滤波器状态机,得到按键当前状态。每次检测的具体过程如下: 

1. 将 IO 口置高 2 个机器周期,此时金属部件及电容 C 对 GND 的电压被充高到 VCC。 

2. 将 IO 口配置为电压比较器输入模式,此时 IO 口状态切换为高阻输入状态,金属部件及电容 C 通过对 GND 的旁路电阻 R 放电,端子电压变化曲线为标准的 RC 放电曲线。 

3. 软件记录循环定时器(GTIM 最高主频运行)的当前值,并等待电压比较器的输出翻转(电压比较器被 配置为与某电压门限比较)。

4. 电压比较器输出翻转后立即记录循环定时器当前值,并结合前次记录的时间记录输出结果。触摸检测过程的相关代码如下:

uint32_t TouchKey_GetValue(uint8_t key, uint8_t ref) 
{ 
    uint32_t CurTime; 
    //VC1  切换通道 
    CW_VC1->CR0_f.INP = key;       // 设置按键通道 
    CW_VC1->DIV_f.DIV = ref;     // 设置按键比较的参考比例 
    // 获取放电时间 
    CW_GPIOB->DIR &= ~((1UL<<8)>>key);   // 按键端口输出,对电容充电 
    __NOP(); 
    __NOP(); 
    CW_GTIM->CNT = 0x0000;        // 计数器清零 
    CW_GPIOB->DIR |= ((1UL<<8)>>key);   // 按键端口输入高阻 
    while((CW_VC1->SR_f.FLTV) == 1 );     // 等到放电到比较点 
    CurTime = CW_GTIM->CNT;        // 获取放电时间 
    return CurTime; 
}

4、 触摸参数及选型倾向 

为了保证检测流程顺利执行,需要选择每一个触摸按键的基础电容 C 和放电电阻 R 以及比较器参考门限 V。DEMO 中,这三个参数一般为 C=4.7pF,R=51KΩ,V=9/64 VDD。

C 和 R 的值,以及比较器参考门限 V 均可根据实际电路测试结果进行调整,调整考量如下: 

1. C 的容量增加会令放电时间更长,在检测程序中将会需要更多的机器周期等待比较器翻转。

2. C 的容量增加会显著增强电路稳定性但对检测灵敏度没有大的影响。 

3. R 的阻值增加会令放电时间更长,在检测程序中将会需要更多的机器周期等待比较器翻转。 

4. R 的阻值增加会降低电路稳定性(高阻易受环境干扰)但对检测灵敏度有明显帮助。 

5. 比较器参考门限 V 过高会降低检测灵敏度,但能节约检测时间。门限 V 过低会削弱抗干扰能力并浪费检 测时间。

5、 调试指引及性能参考 

5.1 示例软件框架介绍 

示例软件占用 1 个基本定时器,利用定时中断并在中断服务程序中执行按键检测过程、定时周期 10 毫秒。每次进入中断服务程序后,顺序扫描 M 个触摸按键的 RC 响应。 

顺序扫描 N 次后,将 RC 响应结果数据提交滤波器状态机。

滤波器状态机输出按键状态结果。

5.2 调试工具 TD_GetBaseResponseRCT 的使用 

示例软件提供一组标定工具来测量当前环境的 RC 响应,执行过程如下:

1. 在没有手指按下的情况下,执行 TD_GetBaseResponseRCT,函数的参数用于选择对应 IO,返回值作 为该按键的基础时长 TB。 

2. 在有手指按下的情况下,执行 TD_GetBaseResponseRCT,函数的参数用于选择对应 IO,返回值作为 该按键的信号时长 TS。 

注 1:每一个按键(IO)的 TB和 TS都应被单独收集并作为滤波器状态机的参数使用。 

注 2:各种温湿度条件下的 TB和 TS都应该在实验室中被采集并用于影响滤波器状态机的参数。 

注 3:比较器门限 V 也是可以针对每一个触摸按键单独选择的,如果某个按键的 TB和 TS无法实现明显的差异, 调节 C、R 和 V 将是唯一有效的途径。 

另:由于本例利用了高阻态 及小信号检测技术,触摸按键的布线要求尽量保持独立性,其金属部件、与 IO 的连线以及 RC 电路周围要尽量避免与其它电路并列共存,否则将大幅提高参数选择及调试难度直至无法完成。

5.3 性能参考

5.png

来源:武汉芯源半导体

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 49

模数转换器(ADC)的主要功能是将模拟量转换为数字量,方便MCU进行处理。下面以CW32L083为例介绍CW系列的模数转换器的特点和功能,并提供演示实例。

一、概述

CW32L083 内部集成一个 12 位精度、最高 1M SPS 转换速度的逐次逼近型模数转换器 (SAR ADC),最多可将 16 路模拟信号转换为数字信号。现实世界中的绝大多数信号都是模拟量,如光、电、声、图像信号等,都要由 ADC 转换成数字信号,才能由 MCU 进行数字化处理。

二、主要特性

• 12 位精度 

• 可编程转换速度,最高达 1M SPS 

• 16 路输入转换通道:13 路外部引脚输入 - 内置温度传感器 - 内置 BGR 1.2V 基准 - 1/3 VDDA 电源电压 

• 4 路参考电压源(Vref):- VDDA 电源电压 - ExRef(PB00)引脚电压 - 内置 1.5V 参考电压 - 内置 2.5V 参考电压 

• 采样电压输入范围:0 ~ Vref

 多种转换模式,全部支持转换累加功能 - 单次转换 - 多次转换 - 连续转换 - 序列扫描转换 - 序列断续转换 

• 支持单通道、序列通道两种通道选择,最大同时支持 8 个序列 

• 支持输入通道电压阈值监测

• 内置信号跟随器,可转换高阻抗输入信号 

• 支持片内外设自动触发 ADC 转换 

• 支持 ADC 转换完成触发 DMA

三、转换时序

ADC 的转换时序如下图所示:

1.png


向 ADC 控制寄存器 ADC_CR0 的 EN 位域写入 1,使能 ADC 模块。 

ADC_CR0.EN 由 0 变为 1 约 40μs 后 ADC_ISR.READY 标志位置 1,表示模拟电路初始化完成,可以开始进行 ADC 转换。 

向 ADC 启动寄存器 ADC_START 的 START 位域写入 1,启动 ADC 转换,转换完成后硬件自动清零。 

ADC 工作时钟 ADCCLK,由系统时钟 PCLK 经预分频器分频得到,通过控制寄存器 ADC_CR0 的 CLK 位域可选择 1 ~ 128 分频


四、工作模式

ADC 控制寄存器 ADC_CR0 的 MODE 位域配置 ADC 工作模式


启动 ADC 转换,可通过向 ADC 启动寄存器 ADC_START 的 START 位域写 1;也可通过其他外设来触发。

2.png

五、实际案例

GTIM1定时器定时1S,定时器1S中断触发启动ADC转换,采样AIN1,并通过GTIM2以PWM方波输出ADC采样值:PWM占空比50%,周期为1Hz-5000Hz,对应ADC的0-4095采样值。

1.配置ADC测试IO口

void ADC_PortInit(void) 
{ 
    REGBITS_SET(CW_SYSCTRL->AHBEN, SYSCTRL_AHBEN_GPIOA_Msk); //打开GPIO时钟 
    REGBITS_SET(CW_SYSCTRL->APBEN2, SYSCTRL_APBEN2_ADC_Msk); //打开ADC时钟 
    PA01_ANALOG_ENABLE();//set PA01 as AIN1 INPUT 
}

2.LED初始化

void LED_Init(void) 
{ 
    GPIO_InitTypeDef GPIO_InitStructure = {0}; 
    REGBITS_SET(CW_SYSCTRL->AHBEN, SYSCTRL_AHBEN_GPIOC_Msk); //打开GPIO时钟 
    /* Configure the GPIO_LED pin */ 
    GPIO_InitStructure.Pins = GPIO_PIN_2 | GPIO_PIN_3; 
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; 
    GPIO_Init(CW_GPIOC, &GPIO_InitStructure); 
    PC02_SETLOW();//LEDs are off. PC03_SETLOW(); 
}

3.PWM IO初始化

void PWM_PortInit(void) 
{ 
    GPIO_InitTypeDef GPIO_InitStructure = {0}; 
    /* PA5 PWM 输出 */ 
    __RCC_GPIOA_CLK_ENABLE(); 
    /* Configure the PWM output pin */ 
    GPIO_InitStructure.Pins = GPIO_PIN_5; 
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; 
    GPIO_Init(CW_GPIOA, &GPIO_InitStructure); 
    PA05_AFx_GTIM2CH1(); 
}

4.GTIM初始化

void GTIM_Init(void) 
{ 
    GTIM_InitTypeDef GTIM_InitStruct = {0}; 
    
    //REGBITS_SET(CW_SYSCTRL->APBEN1, SYSCTRL_APBEN1_GTIM1_Msk); //打开GTIM1 
    __RCC_GTIM1_CLK_ENABLE(); //打开GTIM1时钟 GTIM_InitStruct.Mode = GTIM_MODE_TIME;
    GTIM_InitStruct.OneShotMode = GTIM_COUNT_CONTINUE; 
    GTIM_InitStruct.Prescaler = GTIM_PRESCALER_DIV1024; 
    GTIM_InitStruct.ReloadValue = 62499ul; //T=1s. 
    GTIM_InitStruct.ToggleOutState = DISABLE; 
    GTIM_TimeBaseInit(CW_GTIM1, &GTIM_InitStruct); 
    GTIM_ITConfig(CW_GTIM1, GTIM_IT_OV, ENABLE); 
    NVIC_ClearPendingIRQ(GTIM1_IRQn); 
    NVIC_EnableIRQ(GTIM1_IRQn);
    NVIC_SetPriority(GTIM1_IRQn, 0x03); 
    
    __RCC_GTIM2_CLK_ENABLE();//打开GTIM2时钟 
    GTIM_InitStruct.ReloadValue = 0xFFFFu; 
    GTIM_InitStruct.ToggleOutState = ENABLE;
    GTIM_TimeBaseInit(CW_GTIM2, &GTIM_InitStruct); 
    valuePeriod = GTIM_InitStruct.ReloadValue; 
    valuePosWidth = valuePeriod >> 1u; 
    GTIM_OCInit(CW_GTIM2, GTIM_CHANNEL1, GTIM_OC_OUTPUT_PWM_HIGH); 
    GTIM_SetCompare1(CW_GTIM2, valuePosWidth); 
    GTIM_Cmd(CW_GTIM2, ENABLE); 
}

5.主程序main

uint16_t valueAdc; 
uint32_t valueAdcAcc; 
volatile uint8_t gFlagIrq; 
uint16_t gCntEoc = 0; 
uint8_t cntSample; 
float fTsDegree; 
uint32_t valuePeriod; 
uint32_t valuePosWidth; 
uint32_t valueReload = 0xFFFFu; 
int main(void) 
{   
    uint8_t res; 
    ADC_InitTypeDef ADC_InitStructure = {0}; 
    ADC_WdtTypeDef ADC_WdtStructure = {0};
    ADC_SingleChTypeDef ADC_SingleChStructure = {0}; 
    RCC_HSI_Enable(RCC_HSIOSC_DIV6);     //以下从HSI切换到PLL 
    RCC_PLL_Enable(RCC_PLLSOURCE_HSI, 8000000UL, RCC_PLL_MUL_8); 
    //开启PLL,PLL源为HSI 
    __RCC_FLASH_CLK_ENABLE();//打开FLASH时钟 
    FLASH_SetLatency(FLASH_Latency_3); 
    res = RCC_SysClk_Switch(RCC_SYSCLKSRC_PLL); //切换系统时钟到PLL:64MHz。 
    ADC_PortInit();//配置ADC测试IO口 
    LED_Init();//LED初始化 
    PWM_PortInit();
    GTIM_Init(); 
    ADC_StructInit(&ADC_InitStructure); //ADC默认值初始化 
    ADC_WdtInit(&ADC_WdtStructure); //ADC模拟看门狗通道初始化 
    ADC_InitStructure.ADC_ClkDiv = ADC_Clk_Div128;    //ADCCLK:500KHz. 
    ADC_InitStructure.ADC_InBufEn = ADC_BufEnable; 
    ADC_InitStructure.ADC_SampleTime = ADC_SampTime10Clk; 
    ADC_SingleChStructure.ADC_DiscardEn = ADC_DiscardNull; //配置单通道转换模式
    ADC_SingleChStructure.ADC_Chmux = ADC_ExInputCH1; //选择ADC转换通道 
    ADC_SingleChStructure.ADC_InitStruct = ADC_InitStructure; 
    ADC_SingleChStructure.ADC_WdtStruct = ADC_WdtStructure; 
    ADC_SingleChOneModeCfg(&ADC_SingleChStructure); 
    ADC_ITConfig(ADC_IT_EOC, ENABLE); 
    ADC_EnableIrq(ADC_INT_PRIORITY);
    ADC_ClearITPendingAll(); 
    ADC_Enable();//ADC使能 
    ADC_ExtTrigCfg(ADC_TRIG_GTIM1, ENABLE); //ADC外部中断触发源配置 
    GTIM_Cmd(CW_GTIM1, ENABLE);
    while (1) 
    { 
        while (!(gFlagIrq & ADC_ISR_EOC_Msk)); 
        gFlagIrq = 0u; PC03_TOG(); 
        valueAdc = ADC_GetConversionValue(); 
        valueReload = ((4095u * 125000ul) / (4999u * valueAdc + 4095u) + 1) >> 1; 
        GTIM_SetCounterValue(CW_GTIM2, 0u);     //reset. 
        GTIM_SetReloadValue(CW_GTIM2, valueReload); 
        GTIM_SetCompare1(CW_GTIM2, valuePosWidth); //等待ADC外部中断触发源启动下一次ADC转换 
    } 
}

6.实验展示

通用定时器GTIM1定时1s自动触发ADC模块进行转换,ADC通道为AIN1:PA01。

通用定时器GTIM2将AIN1的ADC采样值转换成频率可变的PWM方波,占空比50%,使用PA05作为PWM输出。ADC采样值为0时,PWM方波频率为1Hz;ADC采样值为4095时,PWM方波频率为5KHz。

3.png

来源:武汉芯源半导体

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 40

页面

订阅 RSS - CW32