CW32L083

前言

红外遥控技术在我们日常生活中的应用可以说是非常广泛了,凡是涉及到遥控人们第一个想到的就是红外遥控。红外遥控的发射电路是采用红外发光二极管来发出经过调制的红外光波,而红外接收电路则由红外接收二极管、三极管或硅光电池组成,它们将红外发射器发射的红外光转换为相应的电信号,再送后置放大器,由于原理简单,实际应用便捷,所以大部分遥控器都采用红外作为调制解调信号。本设计则是通过单片机内置的红外线遥控发射技术,实现对空调的控制功能,达到使空调制冷、制热、温度、风向等功能的实现目的,当然且红外遥控器还具有设计简单、体积小、功耗低等优点。

该空调遥控器的MCU采用的是芯源半导体有限公司推出的一款低功耗、自带IR功能、自带LCD驱动的MCU——CW32L083。CW32L083 内部集成红外调制发送器 (IR),通过两路通用定时器或一路通用定时器与 UART 配合使用,可方便实现各种标准的 PWM 或 PPM 编码方式,也可实现 UART 数据的红外调制发送;CW32L083 内部还集成一个液晶控制器,用于单色无源液晶显示器(LCD)的数字控制与驱动,最多具有 8 个公用端子(COM)和 56 个区段端子(SEG),可以驱动 224(4×56)、324(6×54)或 416(8×52)个 LCD 图像元素,无需外加辅助电路;另外该单片机系统提供的双晶振结构可以对系统时钟进行切换,从而实现空调遥控器的节能设计。

开发记录

第一步:系统总体设计

该空调遥控器是以单片机为核心,由键盘接收用户命令,通过发射编码对空调进行操作并用LCD对当前状态进行显示,无操作状态下则会进入低功耗模式。具体有以下几个功能:

1、自动、制冷、制热、抽湿、通风五种模式设定;

2、二十四小时预约开关机功能;

3、温度设定范围是16℃ 至 30℃;

4、五档风速设定;

5、Sleep模式设定,可自由设定时间;

6、风向设定,90度范围内五个方向设定;

7、一键清除定时功能。

首次装上电池接通电源后,遥控器进入的状态为复位状态,进入复位状态后,液晶显示屏全部被点亮两秒钟,然后保留上一次设定的值和模式(或者默认温度值和模式)。遥控器系统设计框图如下图1所示:

1.png


图1 系统设计框图


第二步:硬件电路设计及PCB制板


根据系统框图,主要分为以下四部分电路:

1、红外发射电路

根据设计电路要实现的功能对红外进行编码,当按压功能指令键盘时,产生经过调制的串行编码,通过激励电路,驱动红外发光二极管,发射给接收端。

2、液晶显示模块电路

本模块才用LCD显示屏与单片机的LCD驱动接口相连,用于读取各项显示数据,并与按键一起用于系统运行参数的设定及运行状态。

3、复位电路

本系统的复位电路上电后或按下开关系统复位,使处于随机状态的内部各寄存器数据复位为原值。

4、按键部分

用于存储功能操作,作为人机交互接口的信息输入、输出。

根据以上设计基础,设计如图2所示的遥控器原理图,图3、图4分别为遥控器的PCB电路板及实物图。

2.png


图2 遥控器原理图

1689644514608454.jpg


图3 遥控器PCB电路板

1689644521298093.jpg


图4 遥控器实物图

第三步:烧录调试

本遥控器的软件部分不便透漏,所以软件设计部分忽略。将程序通过预留的烧录口烧录进去后,把PCB板和遥控器外壳组装起来。装好电池,打开开关,分别测试每个按键是否有反应,自动、制冷、制热、抽湿、通风等模式的设置,风速的调整,出风口方向,睡眠设置等。

来源:CW32生态社区

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

围观 36

前言

线控器,是中央空调的“指挥家”。是空调运行的第一步,也是日常调节的中枢,通过线控器指令的传导,空调就会做出相应的服务。随着空调普及率的提高,空调线控器及遥控器的产量不断上升。又由于单片机的集成度高,功能强,通用性好,且其体积小,重量轻,能耗低,可靠性高,抗干扰能力强等特点,所以大部分空调遥控器和线控器都采用单片机作为主控制器。

芯源推出的CW32L系列产品已全面实现 -40℃ ~ 85℃超宽温度范围和 1.65V~5.5V 超宽工作电压,面向最广泛的各种基础应用。CW32系列HBM ESD、MM ESD、CDM ESD、Latch up@105℃全面达到JEDEC最高等级,所以CW32系列具备稳定可靠的eFLASH制造,确保了工业产品的高可靠性。此次产品的研发就是基于芯源产品的系列进行的,并将对产品进行ESD测试等内容。

开发记录

第一步:硬件设计及PCB制板

此线控器是基于武汉芯源半导体推出的CW32L083低功耗系列产品设计研发而成的,其主要包括MCU、触摸模块、通信模块、红外遥控模块、存储模块、编程接口等部分,设计系统原理框图如图1所示:

1.jpg

图1 系统原理框图

该线控器自带背光,白底黑字液晶,触摸按键,可显示和设置时钟,可预约24小时开关机(倒计时、时刻定时功能),可调节7档风速、上下扫风和左右扫风,可切换自动、制冷、初始、送风、自热等模式,不仅可以通过WiFi与手机相连使用APP控制,还可以接收红外遥控器控制,具有机组参数查询与设置功能,防潮设计、不易受潮。其设计原理图及PCB板实物图分别如图2、图3所示:

2.jpg

图2 线控器原理图

1688639748606695.jpg

图3 线控器PCB板

第二步:软件设计

软件部分主要分为以下几部分内容,软件构成如图4所示:

4.jpg

图4 线控器程序图

  1. LCD显示部分,LCD主要显示温度,风速,模式等系列设置内容,例如模式设置内容为:

/*
@brief 运行模式显示@detail 显示自动、制暖、制冷、抽湿和送风*/
void display_mode(void)
{
复制if (G_CleanState)
  return;
switch(G_SystemMode)
{
  case SYSTEM_MODE_AUTO: 
    lcd_SystemMode_Auto;
    break;
  case SYSTEM_MODE_WARM: 
    lcd_SystemMode_WARM;
    break;
  case SYSTEM_MODE_COLD: 
    lcd_SystemMode_COLD;
    break;
  case SYSTEM_MODE_COLD_WET: 
    //lcd_SystemMode_COLD;
    lcd_SystemMode_WET;
    break;
  case SYSTEM_MODE_WET: 
    lcd_SystemMode_WET;
    break;
  case SYSTEM_MODE_WIND:
    lcd_SystemMode_WIND;
    break;
}}

 2. 蜂鸣器部分,主要实现功能是按键响应,例程如下:

void ppg_program(void)
{
if(key_keepon_beep)
{
PPG_time=0;
return;}
switch(PPG_type)
{
case 0: ppg_off(); break;
case 1: ppg_type1(); break;
case 2: ppg_type2(); break;
case 3: ppg_type3(); break;
case 4: ppg_type4(); break;
case 5: ppg_type5(); break;
case 6: ppg_type6();break;
default: ppg_off(); break;
}}

3. 存储部分,存储用的是24C04,通过使用IIC通讯方式与MCU进行连接的,用来存储用户设置的相关信息等,例程如下:

uint8_t i=0;
I2C_SDA_OUTPUT();
delay_5us();
for(i=0;i< 8;i++)
{   
    if (Byte & 0x80)
        I2C_SDA_HIGH();
    else
        I2C_SDA_LOW();
    NOP();     
    I2C_SCL_HIGH();
    delay_5us();
    I2C_SCL_LOW();
    delay_5us();
    Byte < <= 1;
}   
I2C_SDA_INPUT();
I2C_SCL_HIGH();
delay_5us();
if (I2C_SDA_READ())
    i = 0x01;
else
    i = 0x00;
I2C_SCL_LOW();
return i;}

4. 按键部分,按键主要是用来处理按键信息,实现用户想要设置的内容,例程如下:

//功能部分
void key2_deal(void)
{
backlight_cnt=0;
backlight_flag=1;
if(self_check_flag)
  return;
if (G_FeatureSetStatus)
  return;
if (set_status == SET_CLOCK)
  return;
if (G_CleanState)
  return;/******************************************************/
复制/* (1)短按释放 */
/******************************************************/
if(key2_down_flag)
{
  if(set_status)
  {
    set_status=NO_SET;
    G_IrSendFlag |= IR_NORMAL_SEND_FLAG;
    G_TxTime1sCnt=0;
    if(beep_enable)
    {
      ppg_off();PPG_type=1;PPG_time=0;
    }
  }
  else if(server_set_status)
  {
    server_change_deal();
    beep_enable_deal(1);
  }
  else if(G_NanoeSingle)
  {
    G_NanoeSingle=0;
    nanoe_single_write = 1;
    G_SystemMode=G_NanoeMode;
    system_mode_write=1;
    beep_enable_deal(1);
    G_IrSendFlag |= IR_NORMAL_SEND_FLAG;
    G_TxTime1sCnt=0;
 
  }
  else
  {
    if(mode_lock==0)    //模式 0--自动  1-制暖  2--制冷  3--抽湿 4--送风 
    {
      //G_FreshAir = 0;
      if (G_StrongColdState)
      {
        G_StrongColdState = 0;
        strong_cold_write = 1;
        //G_Rx0SendFlag |= RX0_SEND_FLAG_NORMAL;
      }
      if (G_StrongWarmState)
      {
        G_StrongWarmState = 0;
        strong_warm_write = 1;
        //G_Rx0SendFlag |= RX0_SEND_FLAG_NORMAL;
      }

5. 触摸部分,由于CW32L083本身没有触摸功能,所以另外又搭配了YS806电容感应式芯片,此芯片也是通过I2C与主芯片进行通讯的,具体部分例程如下:

uint8_t I2C_806_ReadByte(uint8_t ack)
{
unsigned char i, Data;
I2C_806_SDA_INPUT();
Data = 0x00;
for(i = 0; i < 8; i++){
Data < <= 1;I2C_806_SCL_HIGH();
DelayIIC(HALF_CLK_CYCLE);if(I2C_806_SDA_READ()){
Data |= 0x01;
} else { }    DelayIIC(HALF_CLK_CYCLE);
I2C_806_SCL_LOW();
DelayIIC(CLK_CYCLE);}
I2C_806_SDA_OUTPUT(); //send ACK or not
if(ack){
I2C_806_SDA_HIGH();} else {
I2C_806_SDA_LOW();}
I2C_806_SCL_HIGH();
DelayIIC(CLK_CYCLE);
I2C_806_SCL_LOW();
DelayIIC(CLK_CYCLE);
return Data;
}

除以上部分外还有其他例如背光、红外等程序内容,在此就不一一赘述。

第三步:下载调试

线控器安装液晶屏后,只需下载程序即可上电调试。为了方便刷程序,将程序的hex文件烧录至离线编程器中,四线插入正确按下烧录键即可烧录成功。烧录后通过按不同的触控按钮,实现其相对应的功能。然后再对产品进行1.5KV电压干扰下测试,测试结果展示如下图5所示,其功能及状态属于正常,CW32具有超强抗干扰能力。来自传说中的“小黑盒”隔空点灯神技攻击——MCU抗干扰实验系列专题(1)

5.jpg

图5 1.5KV干扰下测试状态

第四步:总结

以上即为本次线控器设计的全部基本内容,芯源推出的CW32L系列产品已全面实现 -40℃ ~ 85℃超宽温度范围和 1.65V~5.5V 超宽工作电压,面向最广泛的各种基础应用。CW32系列HBM ESD、MM ESD、CDM ESD、Latch up@105℃全面达到JEDEC最高等级,所以CW32系列具备稳定可靠的eFLASH制造,确保了工业产品的高可靠性。此次产品的研发就是基于芯源产品的系列进行的,并将对产品进行ESD测试等内容。可以方便快捷的满足客户的需求,控制空调温度,调节空调模式、风速等,当然也有不足,后续将继续改进。

来源: CW32生态社区

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

围观 64

本文主要介绍CWL083VCT6芯片在不同主频下的功耗测试方法和测试结果。

1.HSIOSC时钟

HSIOSC 时钟由内部 RC 振荡器产生,不需要外部电路,比 HSE 时钟的成本低,启动速度快。HSIOSC 时钟频率固定为 48MHz,频率精度低于 HSE 时钟。RC 振荡器输出时钟的频率受芯片加工过程、工作电压、环境温度等因素影响,CW32L083 提供了 HSIOSC 时钟频率校准功能,用户可通过设置内置高频时钟控制寄存器 SYSCTRL_HSI 的 TRIM 位域值来校准 HSIOSC 时钟频率,HSIOSC 内部高速 RC 振荡器在芯片上电后,默认处于开启状态,用户可通过设置系统控制寄存器的 SYSCTRL_CR1 的HSIEN 位域为 0 来关闭。如用户停止并重新启动了 HSIOSC 振荡器,可通过内置高频时钟控制寄存器 SYSCTRL_HSI的 STABLE 标志位来确定 HSI 时钟是否稳定,STABLE 标志为 1 表示 HSIOSC 时钟已稳定,为 0 则表示 HSIOSC 时钟还未稳定。

HSIOSC 时钟经过分频后输出 HSI 时钟,分频系数通过内置高频时钟控制寄存器 SYSCTRL_HSI 的 DIV 位域设置,有效分频系数为 1、2、4、6、8、10、12、14、16,上电后默认值为 6,所以 HSI 时钟默认频率为 8MHz。

2.PLL时钟

CW32L083 内部集成锁相环 PLL 电路,可对输入时钟源进行锁相倍频输出 PLL 时钟。用户可通过内置锁相环控制寄存器 SYSCTRL_PLL 的 SOURCE 位域选择 PLL 的输入参考时钟源,如下表所示

1.png

锁相环倍频系数通过内置锁相环控制寄存器 SYSCTRL_PLL 的 MUL 位域进行设置,可设置范围为 2 ~ 12,默认值 为 8。为保证锁相环的锁定收敛速度及输出时钟相噪性能,用户需根据实际的输入参考时钟频率和输出时钟频率分别设置 SYSCTRL_PLL.FREQIN 和 SYSCTRL_PLL.FREQOUT 位域的值。

2.png

3.png

PLL 默认处于关闭状态,通过设置系统控制寄存器 SYSCTRL_CR1 的 PLLEN 位域为 1 来启动。PLL 启动后,芯片 内部时钟监控模块检测到一定数量的 PLL 时钟信号,则认为 PLL 时钟已稳定。检测时钟数量可通过内置锁相环控制寄存器 SYSCTRL_PLL 的 WAITCYCLE 位域进行设置,通过内置锁相环控制寄存器 SYSCTRL_PLL 的 STABLE 标志位,可确定 PLL 时钟是否稳定,STABLE 标志为 1 表 示 PLL 时钟已稳定,为 0 则表示 PLL 时钟还未稳定。

修改 PLL 参数流程如下: 

步骤 1:设置 SYSCTRL_CR1.PLLEN 为 0,关闭 PLL; 

步骤 2:等待 SYSCTRL_PLL.STABLE 标志被系统硬件清零; 

步骤 3:更改 PLL 的参数; 

步骤 4:设置 SYSCTRL_CR1.PLLEN 为 1,启动 PLL; 

步骤 5:等待 SYSCTRL_PLL.STABLE 标志被系统硬件置 1,标识 PLL 时钟已稳定。

3.实例演示

通过按键KEY1中断调节运行主频(4M/12M/24M/48M/64M),LCD显示对应数字。

(1)初始化GPIO

void GPIO_Configuration(void) 
{ 
    GPIO_InitTypeDef GPIO_InitStruct = {0}; 
    __RCC_GPIOA_CLK_ENABLE(); 
    GPIO_InitStruct.IT = GPIO_IT_FALLING; //KEY1 -- PA04 
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 
    GPIO_InitStruct.Pins = GPIO_PIN_4; 
    GPIO_Init(CW_GPIOA, &GPIO_InitStruct); 
    GPIO_ConfigFilter(CW_GPIOA, bv4, GPIO_FLTCLK_LSI); 
}

(2)GPIO中断控制函数

void GPIOA_IRQHandlerCallback(void) 
{ 
    if(CW_GPIOA->ISR_f.PIN4) 
    { 
        GPIOA_INTFLAG_CLR(bv4); 
        Key1Count++; 
        switch(Key1Count) 
        { 
            case 1: 
            CW_LCD->RAM0 = 0x0603;//4 
            RCC_HSI_Enable(RCC_HSIOSC_DIV12); 
            RCC_SysClk_Switch(RCC_SYSCLKSRC_HSI); //切换系统时钟到HSI 4MHz 
            RCC_PLL_Disable(); //关闭PLL 
            break; 
            case 2: 
            CW_LCD->RAM0 = 0x030e0005;//12 RCC_HSI_Enable(RCC_HSIOSC_DIV4); 
            break; 
            case 3: 
            CW_LCD->RAM0 = 0x0603030e;//24 RCC_HSI_Enable(RCC_HSIOSC_DIV2); 
            break; 
            case 4: 
            CW_LCD->RAM0 = 0x0f0f0603;//48 
            RCC_HSI_Enable(RCC_HSIOSC_DIV6); 
            RCC_SysClk_Switch(RCC_SYSCLKSRC_HSI); //切换系统时钟到HSI 8MHz 
            RCC_PLL_Disable(); //关闭PLL 
            FLASH_SetLatency(FLASH_Latency_2); 
            //频率大于24M需要配置FlashWait=2 
            CW_SYSCTRL->AHBEN_f.FLASH = 0; //关闭FLASH时钟 
            RCC_HSI_Enable(RCC_HSIOSC_DIV1); 
            RCC_SysClk_Switch(RCC_SYSCLKSRC_HSI); //切换系统时钟到HSI 48MHz 
            break; 
            case 5: 
            CW_LCD->RAM0 = 0x0603050f;//64 
            RCC_HSI_Enable(RCC_HSIOSC_DIV6); 
            RCC_PLL_Enable(RCC_PLLSOURCE_HSI, 8000000, RCC_PLL_MUL_8); 
            //开启PLL,PLL源为HSI 8MHz 
            FLASH_SetLatency(FLASH_Latency_3); 
            //频率大于48M需要配置FlashWait=3 
            CW_SYSCTRL->AHBEN_f.FLASH = 0; //关闭FLASH时钟 
            RCC_SysClk_Switch(RCC_SYSCLKSRC_PLL); //切换系统时钟到PLL 
            break; 
            case 6: 
            CW_LCD->RAM0 = 0; 
            CW_LCD->RAM1 = 0; 
            CW_LCD->RAM8 = 0; 
            CW_LCD->RAM9 = 0; 
            Key1Count = 0; break; 
        } 
    } 
}

(3)初始化LCD

void LCD_Configuration(void) 
{ 
    LCD_InitTypeDef LCD_InitStruct = {0}; 
    LCD_InitStruct.LCD_Bias = LCD_Bias_1_3; 
    LCD_InitStruct.LCD_ClockSource = LCD_CLOCK_SOURCE_LSI; 
    LCD_InitStruct.LCD_Duty = LCD_Duty_1_4; 
    LCD_InitStruct.LCD_ScanFreq = LCD_SCAN_FREQ_256HZ; 
    LCD_InitStruct.LCD_VoltageSource = LCD_VoltageSource_Internal;
     __RCC_LCD_CLK_ENABLE(); 
     RCC_LSI_Enable(); //启动LSI为LCD提供时钟 
     LCD_Init(&LCD_InitStruct); //基本配置 
     LCD_COMConfig(LCD_COM0 | LCD_COM1 | LCD_COM2 | LCD_COM3, ENABLE); //SEG 
     LCD_SEG0to23Config(LCD_SEG0 | LCD_SEG1 | LCD_SEG2 | LCD_SEG3 | LCD_SEG4 | 
     LCD_SEG5 | LCD_SEG6 | LCD_SEG7, ENABLE); 
     LCD_SEG32to55Config(LCD_SEG32 | LCD_SEG33 | LCD_SEG34 | LCD_SEG35 | LCD_SEG36 | 
     LCD_SEG37 | LCD_SEG38 | LCD_SEG39, ENABLE); 
     LCD_ContrastConfig(LCD_Contrast_Level_2); //显示对比度,仅内部电阻模式时有效 
     LCD_DriveVoltageConfig(LCD_INRS_LEVEL_0); //功耗最小 
     CW_LCD->RAM0 = 0x0f0f; 
     LCD_Cmd(ENABLE); 
}

(4)配置嵌套的矢量中断控制器

void NVIC_Configuration(void) 
{ 
    __disable_irq(); 
    NVIC_SetPriority(GPIOA_IRQn, 0); 
    NVIC_EnableIRQ(GPIOA_IRQn); 
    __enable_irq(); 
}

(5)主函数

int32_t main(void) 
{
    RCC_HSI_Enable(RCC_HSIOSC_DIV6); 
    GPIO_Configuration(); 
    LCD_Configuration(); 
    NVIC_Configuration(); 
    while(1){} 
}

4.测试结果

将电流表串接在单板J23跳线上,单板上电,默认主频为8MHz然后通过KEY1按键,控制主频在4 MHz -12 MHz -24 MHz -48 MHz -64 MHz之间进行切换,记录不同主频下的电流值,如下:

4.png

来源:武汉芯源半导体

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

围观 37

一、简介

半双工即Half duplex Communication,是指在通信过程的任意时刻,信息既可由A传到B,又能由B传A,但同时只有一个方向上的传输存在。由于这种方式要频繁变换信道方向,故效率低,但可以节约传输线路。半双工方式适用于终端与终端之间的会话式通信。

二、实际操作(以CW32L083为例)

设置 UARTx_CR2.SIGNAL 为 1 使 UART 工作于单线半双工工作模式。在该模式下,使用 UARTx_TXD 引脚进行数据的发送和接收,不占用 UARTx_RXD 引脚(UARTx_RXD 可作通用 IO 使用)。写数据到 UARTx_TDR 寄存器后,UARTx_TXD 引脚立即进入发送状态,输出 UARTx_TDR 寄存器中的数据。数据 发送完成后,UARTx_TXD 引脚恢复到常态的接收状态。没有发送数据时,UARTx_TXD 引脚处于接收状态,数据接收完成后,接收完成标志位 UARTx_ISR.RC 会被硬件置 位,此时应尽快读取 UARTx_RDR 寄存器,并清除 UARTx_ISR.RC 标志位。

1.png

UART工作在单线半双工模式时,UARTx_TXD引脚需要配置为开漏输出。另外用户应采取适当的应用层保护机制,以确保不会出现多主机同时向总线发送数据。

三、UART单线半双工通信示例

硬件采用CW32L083VxTx StartKit单板,用杜邦线连接PA08和PA06引脚。

UARTy查询方式发送TxBuffer1缓冲区中的数据,UARTz查询方式接收数据,并存储到RxBuffer2缓冲区。

UARTz查询方式发送TxBuffer2缓冲区中的数据,UARTy查询方式接收数据,并存储到RxBuffer1缓冲区。

比较TxBuffer1和RxBuffer2、TxBuffer2和RxBuffer1,如果数据一致,则LED1亮,否则LED2亮。

1、配置RCC

void RCC_Configuration(void) 
{ 
    RCC_HSI_Enable(RCC_HSIOSC_DIV6); //SYSCLK = HSI = 8MHz = HCLK = PCLK 
    RCC_AHBPeriphClk_Enable(UARTy_GPIO_CLK | UARTz_GPIO_CLK | 
    RCC_AHB_PERIPH_GPIOC, ENABLE); //外设时钟使能 
    UARTy_APBClkENx(UARTy_CLK, ENABLE); 
    UARTz_APBClkENx(UARTz_CLK, ENABLE); 
}

2、配置GPIO

void GPIO_Configuration(void) 
{ 
    GPIO_InitTypeDef GPIO_InitStructure = {0}; 
    UARTy_AFTX; //UART TX 复用 
    UARTz_AFTX; U
    ARTy_TXPUR; //UART TX PUR 
    UARTz_TXPUR; 
    GPIO_InitStructure.Pins = UARTy_TxPin; 
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; //开漏输出
    GPIO_Init(UARTy_GPIO, &GPIO_InitStructure); 
    GPIO_InitStructure.Pins = UARTz_TxPin; 
    GPIO_Init(UARTz_GPIO, &GPIO_InitStructure); 
    
    GPIO_InitStructure.Pins = GPIO_PIN_3 | GPIO_PIN_2; //PC3 LED1 / PC2 LED2 
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; 
    GPIO_Init(CW_GPIOC, &GPIO_InitStructure); P
    C03_SETLOW();//LED灭 
    PC02_SETLOW(); 
}

3、配置UART

void UART_Configuration(void) 
{ 
    UART_InitTypeDef UART_InitStructure = {0}; 
    
    UART_InitStructure.UART_BaudRate = UARTyz_BaudRate; // 波特率 
    UART_InitStructure.UART_Over = UART_Over_16; // 采样方式 
    UART_InitStructure.UART_Source = UART_Source_PCLK; // 传输时钟源
    UCLK UART_InitStructure.UART_UclkFreq = UARTyz_UclkFreq; // 传输时钟UCLK频率 
    UART_InitStructure.UART_StartBit = UART_StartBit_FE; // 起始位判定方式 
    UART_InitStructure.UART_StopBits = UART_StopBits_1; // 停止位长度 
    UART_InitStructure.UART_Parity = UART_Parity_No ; // 校验方式 
    UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None; 
    UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx; // 发送/接收使能 
    UART_Init(UARTy, &UART_InitStructure); 
    UART_Init(UARTz, &UART_InitStructure); 
}

4、定义变量

//UARTy 
#define  UARTy                         CW_UART1 
#define  UARTy_CLK                   RCC_APB2_PERIPH_UART1 
#define  UARTy_APBClkENx               RCC_APBPeriphClk_Enable2 
#define  UARTy_GPIO_CLK                RCC_AHB_PERIPH_GPIOA 
#define  UARTy_GPIO                    CW_GPIOA 
#define  UARTy_TxPin                    GPIO_PIN_8 
#define  UARTy_AFTX                    PA08_AFx_UART1TXD() 
#define  UARTy_TXPUR                   PA08_PUR_ENABLE(); 

//UARTz 
#define  UARTz                         CW_UART2 
#define  UARTz_CLK                     RCC_APB1_PERIPH_UART2 
#define  UARTz_APBClkENx               RCC_APBPeriphClk_Enable1 
#define  UARTz_GPIO_CLK                RCC_AHB_PERIPH_GPIOA 
#define  UARTz_GPIO                    CW_GPIOA 
#define  UARTz_TxPin                    GPIO_PIN_6 
#define  UARTz_AFTX                    PA06_AFx_UART2TXD() 
#define  UARTz_TXPUR                   PA06_PUR_ENABLE() 
#define  UARTyz_BaudRate               9600 
#define  UARTyz_UclkFreq                8000000 
#define  TxBufferSize1                   (ARRAY_SZ(TxBuffer1) - 1) 
#define  TxBufferSize2                   (ARRAY_SZ(TxBuffer2) - 1) 
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus; 
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength); 
uint8_t TxBuffer1[] = "\r\nCW32L083 UART HalfDuplex: UARTy -> UARTz\r\n"; 
uint8_t TxBuffer2[] = "\r\nCW32L083 UART HalfDuplex: UARTz -> UARTy\r\n"; 
uint8_t RxBuffer1[TxBufferSize2]; uint8_t RxBuffer2[TxBufferSize1]; 
uint32_t NbrOfDataToRead1 = TxBufferSize2; 
uint32_t NbrOfDataToRead2 = TxBufferSize1; 
uint8_t TxCounter1 = 0, RxCounter1 = 0; 
uint8_t TxCounter2 = 0, RxCounter2 = 0; 
volatile TestStatus TransferStatus1 = FAILED, TransferStatus2 = FAILED;

5、主程序

int32_t main(void) 
{   
    RCC_Configuration();//配置RCC 
    GPIO_Configuration();//配置GPIO 
    UART_Configuration();//配置UART 
    UART_HalfDuplexCmd(UARTy, ENABLE); //单线半双工 UARTy 
    UART_HalfDuplexCmd(UARTz, ENABLE); //单线半双工 UARTz 
    while(NbrOfDataToRead2--)   //UARTy -> UARTz 
    { 
        //UARTy发送一个字节数据 
        UART_SendData_8bit(UARTy, TxBuffer1[TxCounter1++]); 
        while(UART_GetFlagStatus(UARTy, UART_FLAG_TXE) == RESET); 
        //UARTz 等待RC 
        while(UART_GetFlagStatus(UARTz, UART_FLAG_RC) == RESET); 
        UART_ClearFlag(UARTz, UART_FLAG_RC); 
        RxBuffer2[RxCounter2++] = UART_ReceiveData_8bit(UARTz); 
    } 
    while(NbrOfDataToRead1--)//UARTz -> UARTy 
    { 
        //UARTz发送一个字节数据 
        UART_SendData_8bit(UARTz, TxBuffer2[TxCounter2++]); 
        while(UART_GetFlagStatus(UARTz, UART_FLAG_TXE)== RESET); 
        //UARTy 等待RC 
        while(UART_GetFlagStatus(UARTy,UART_FLAG_RC) == RESET); 
        UART_ClearFlag(UARTy, UART_FLAG_RC); 
        RxBuffer1[RxCounter1++] = UART_ReceiveData_8bit(UARTy); 
    } 
    //检查收发数据一致性 
    TransferStatus1 = Buffercmp(TxBuffer1, RxBuffer2, TxBufferSize1); 
    TransferStatus2 = Buffercmp(TxBuffer2, RxBuffer1, TxBufferSize2); 
    if(TransferStatus1 == PASSED && TransferStatus2 == PASSED) //PASSED 
    { 
        //LED1亮 
        PC03_SETHIGH(); 
    } 
    else //FAILED 
    { 
        PC02_SETHIGH();//LED2亮 
    } 
    while(1) 
    { 
    } 
}

6、测试结果:UART半双工通信方式工作正常, LED1亮。

来源:武汉芯源半导体

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

围观 206

CW32L083 内部集成 2 个模拟电压比较器(VC),用于比较两路模拟输入电压,并将比较结果从引脚输出。两路信号的正端支持8路外部模拟输入,负端既支持外部输入,也支持内部电压基准等四种内部电压参考。比较结果输出具有滤波功能、迟滞窗口功能,以及极性选择。支持比较中断,可用于低功耗模式下唤醒 MCU。

模拟电压比较器主要特性

• 双路模拟电压比较器 VC1、VC2

• 内部64阶电阻分压器

• 多达8路外部模拟信号输入

• 4路片内模拟输入信号

- 内置电阻分压器输出电压

- 内置温度传感器输出电压

- 内置1.2V基准电压 

- ADC参考电压

• 可选择输出极性

• 支持迟滞窗口比较功能 

• 可编程的滤波器和滤波时间 

• 3种中断触发方式,可组合使用 

- 高电平触发 

- 上升沿触发 

- 下降沿触发 

• 支持低功耗模式下运行,中断唤醒 MCU

下图为模拟电压比较器的功能框图:

1.png


VC模拟电压比较器将两路模拟信号比较时可配置多种参数,如VC1_CR0.EN和VC1_CR0.HYS位分别控制VC使能及VC迟滞窗口配置。VC1_CR0.POL控制输出结果极性,后端还有窗口比较功能配置及数字滤波模块的配置。

VC1、VC2 的正负端输入选择,由控制寄存器 VCx_CR0 的 INP、INN 位域选择,如下表所示:

2.png

模拟电压比较器支持 8路外部模拟信号输入,用户必须将对应 GPIO端口配置为模拟功能(GPIOx_ANALOG.PINy = 1)。模拟电压比较器支持将比较结果从引脚输出,用户必须将对应 GPIO 端口配置为数字输出,同时选择功能复用。VC1、VC2 支持的输入输出引脚如下表所示:

3.png

模拟电压比较器还具有延迟/响应时间配置,从VC使能或VC的正负两端输入电压变化,到电压比较器输出正确比较结果的时间,被定义为比较器的延迟/响应时间。延迟/响应时间由控制寄存器 VCx_CR0 的 RESP 位域配置,响应时间值从200ns到20μs四档可调。

模拟电压比较器可进行输出极性选择,由控制寄存器VCx_CR0的POL位域设置,POL为1,即正端大于负端时VCx输出低电平;POL为0,正端大于负端时VCx输出高电平。

模拟电压比较器具有数字滤波功能,电压比较器内置的数字滤波器,用于对电压比较器的输出信号进行数字滤波,由控制寄存器VCx_CR1的FLTEN位域控制,FLTEN为1使能数字滤波,FLTEN为0禁止数字滤波。

模拟电压比较器支持迟滞功能,使用迟滞功能后,比较器的输出结果不会随输入信号的变化而立即翻转,而是在两路输入信号的偏移值高于或低于迟滞阈值电压后才发生翻转。迟滞阈值电压由控制寄存器VCx_CR0的HYS位域决定,配置为00时,没有迟滞;配置为01时迟滞窗口大约10mV;配置为10时,迟滞窗口大约为20mV;配置为11时,迟滞窗口大约30mV。

模拟电压比较器支持窗口比较功能,可将VC1和VC2的比较结果进行异或操作后输出,由控制寄存器VCx_CR0的WINDOW位域使能。WINDOW为1时,VCx_OUTW信号为 VC1_OUTP信号与VC2_OUTP 信号的异或值;WINDOW为0时,VCx_OUTW信号与VCx_OUTP 信号电平相同。

模拟电压比较器支持BLANK窗口功能,在保持VCx模块工作的同时,如果想暂时停止电压比较功能,或者为避免某些应用系统(比如电机控制)中,被监测信号短时间的合理波动造成电压比较器的输出电平发生不必要的翻转,本芯片的电压比较器增加了BLANK窗口功能,即当指定的外部触发条件启动BLANK窗口时,在设定的BLANK窗口期内,不进行电压比较,电压比较器的输出电平保持当前电平状态。BLANK窗口期之后,电压比较器恢复正常工作。BLANK窗口持续时间,由控制寄存器 VCx_CR1的BLANKFLT位域配置。BLANK窗口的触发启动条件,由控制寄存器VCx_CR1的 BLANKCH1B、BLANKCH2B、BLANKCH3B位域配置,分别由ATIM的CH1B、CH2B、CH3B上升沿触发启动BLANK窗口。

CW32L083 的电压比较器支持在低功耗模式下工作,比较中断可将芯片从低功耗模式下唤醒。设置控制寄存器 VCx_CR0 的 IE 位域为 1,使能 VCx 中断,产生中断时状态寄存器 VCx_SR 的中断标志位 INTF 会 被硬件置 1,用户可以向 INTF 位写 0,清除中断标志。 

设置控制寄存器 VCx_CR1 的 HIGHIE、RISEIE、FALLIE 位域,可选择不同的中断触发方式:

• HIGHIE 为 1,VCx_OUT 输出信号高电平触发中断 

• RISEIE 为 1,VCx_OUT 输出信号上升沿触发中断 

• FALLIE 为 1,VCx_OUT 输出信号下降沿触发中断

根据上述内容介绍以下例程,通过VC模块输出信号的上升沿/下降沿触发中断功能。

//VC I/O初始化
void VC_PortInit(void)
{

    GPIO_InitTypeDef GPIO_InitStructure = {0};
    //打开GPIO时钟
    REGBITS_SET( CW_SYSCTRL->AHBEN, SYSCTRL_AHBEN_GPIOA_Msk );
    //打开VC时钟
    REGBITS_SET( CW_SYSCTRL->APBEN2, SYSCTRL_APBEN2_VC_Msk );

    //set PA11 as output
    GPIO_InitStructure.Pins = GPIO_PIN_11;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
    //set PA11 as VC output
    PA11_AFx_VC1OUT();
    //set PA00 as VC1_CH0 P-INPUT
    PA00_ANALOG_ENABLE();
    //set PA01 as VC1_CH1 N-INPUT
    PA01_ANALOG_ENABLE();
}

int main(void)
{
    VC_InitTypeDef  VC_InitStruct = {0};
    VC_BlankTypeDef  VC_BlankStruct = {0};
    VC_OutTypeDef  VC_OutStruct = {0};
    
    //LED初始化
    LED_Init();
    
    //配置测试IO口
    VC_PortInit();
    //VC通道初始化
    VC_InitStruct.VC_InputP = VC_InputP_Ch0;//将VC正端输入为PA00的输入信号  
    VC_InitStruct.VC_InputN = VC_InputN_Bgr1P2; //将VC负端输入设置为内部1.2V基准电压
    VC_InitStruct.VC_Hys = VC_Hys_10mV;//将VC迟滞功能配置为10mV
    VC_InitStruct.VC_Resp = VC_Resp_High;//VC反应速度为高速
    VC_InitStruct.VC_FilterEn = VC_Filter_Enable;//VC数字滤波模块开启
        VC_InitStruct.VC_FilterClk = VC_FltClk_RC150K;//VC数字滤波时钟为150KHz的RC振荡器
        VC_InitStruct.VC_FilterTime = VC_FltTime_4095Clk;//VC的数字滤波时间配置为滤波小于4095个时钟信号
        VC_InitStruct.VC_Window = VC_Window_Disable;//VC窗口比较功能关闭
        VC_InitStruct.VC_Polarity = VC_Polarity_Low;
        VC1_ChannelInit(&VC_InitStruct);
        //VC Blank窗口初始化
        VC1VC2_BlankInit(&VC_BlankStruct);
        VC1_BlankCfg(&VC_BlankStruct);
        //VC输出连接初始化
        VC1VC2_OutInit(&VC_OutStruct);
        VC1_OutputCfg(&VC_OutStruct);
        //VC中断设置
        VC1_ITConfig(VC_IT_FALL | VC_IT_RISE, ENABLE);
        VC1_EnableIrq(VC_INT_PRIORITY);>
        VC1_ClearIrq();
        VC1_EnableChannel();

 while (1)
{
  if(gFlagIrq)
   {
     PC03_TOG();
     gFlagIrq = FALSE;
   }
 }
}

//LED I/O初始化
void LED_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure = {0};
        //打开GPIOC时钟
        REGBITS_SET(CW_SYSCTRL->AHBEN, SYSCTRL_AHBEN_GPIOC_Msk);
        GPIO_InitStructure.Pins = GPIO_PIN_2 | GPIO_PIN_3;
        GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_Init(CW_GPIOC, &GPIO_InitStructure);

        //LED的初始状态为灭
        PC02_SETLOW();
        PC03_SETLOW();
}

//VC1的中断服务函数
void VC1_IRQHandler(void)
{
        VC1_ClearIrq();
        gFlagIrq = TRUE;
}

实验现象

使用电源向PA00输入电压,PA11被复用为VC1的比较结果输出引脚,当电压大于1.2V时, PA11输出高电平,当PA00输入电压小于1.2V时,PA11输出低电平,而当PA00的输入电压由1.2V以下变为1.2V以上或者从1.2V以上变为1.2V以下,LED的状态会发生翻转。

来源:武汉芯源半导体

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

围观 44

在政策引领支持、市场需求和技术发展的全面推动下,智能表计市场高速发展。目前我国表计市场仍处于传统机械表和智能表共存的局面,并且水、电、气、热四大智能表的发展程度也各不相同。而表计智能化的浪潮中,元器件无疑是举足轻重的一环。

MCU在表计行业的应用发展进程

1.png

表计行业作为一个专有的应用行业,兼具消费行业和工业行业的一些特性,既具备消费行业广泛的市场前景,同时又具有工业行业对MCU产品的稳定性、可靠性的更高要求。同时,智能表计行业也是联网化比例较高的一个应用场景,对MCU产品的功能、性能、可靠性、低功耗等要求也更高。

相比可穿戴、智能家居、消费电子类等行业,表计行业需要MCU 365天、24小时全天候持续稳定运行,并且需要长期运行10~16年,这对MCU的可靠性和稳定性有很高的要求,这也可以理解为表计行业有较高的技术门槛。

燃气表产品算法和功能相对比水表复杂,对表计产品的升级功能也有一定要求,除了MCU产品的低功耗特性外,还要有较大的存储空间来进行OTA升级备份处理。同时,智能燃气表除了机械数字显示外,还需要LCD段码屏显示,这需要MCU支持段码屏驱动模块。因此燃气表对MCU产品的要求更高一点。

2.png

武汉芯源半导体MCU芯片在智能燃气表领域的应用也迎来了快速的发展,已应用于相关产品方案。今天介绍的这款产品就是武汉芯源半导体CW32L083在智能燃气表的应用方案。

3.png

燃气表控制板方案特色:

01)采用NB-IoT 技术,满足物联网燃气表对小数据流、低通讯频率、低功耗的需求的各种需求,且自身具备的广覆盖、低成本、大容量等优势;

02)优异的低功耗技术平台,实现超低的运行功耗和待机功耗,保证燃气表系统实现长效、稳定的运行;

03)最大支持256K FLASH+24K RAM的大资源配置,适配智能燃气表方案上的远传通信、操作系统、在线升级以及多功能化的发展趋势;

04)集成了LCD驱动、带校准补偿的RTC,高精度ADC,以及丰富的UART、 LPUART、I2C、SPI等通用外设接口,其中LPUART支持低功耗下多种模式唤醒;

05)具有强大的电源管理系统(支持 PDR、 BOR、LVD 等电源管理单元),当燃气表电池电压低于一定阀值时可以进行紧急数据保存,确保产品处于安全状态;

06)内置安全加密模块(支持AES硬件运算单元 128/192/256-bit,支持 ECB/CBC/CTR/GCM/ GMAC 模式),配合应用方案可实现数据的安全化;

CW32L083VCT6在燃气表的应用框图

4.png

CW32L083VCT6特色及优势点:

● ARM Cortex-M0+ 32位内核;

● 最多256K Flash,24K SRAM,数据可保持25年之久;

● 内置高达8x52段LCD驱动;

● VLCD电荷泵,供电电压下降不影响显示对比度;

● 支持低功耗模式Deep Sleep,含六路低功耗UART;

● 内置独立校准的RTC,允许独立关断各外设时钟;

● 内部集成IR调制器,最高数据速率 115.2kbps;

武汉芯源半导体低功耗MCU芯片CW32L083系列具备超低功耗、高可靠性、资源丰富等特点,在智能燃气表应用方面,可以更高效进行数据的采集、显示、存储、传输等一系列功能。

有关芯片购买事宜,请咨询武汉芯源的销售和官方代理商。更多MCU详细信息,请访问武汉芯源官方网站:https://www.whxy.com

来源:武汉芯源半导体

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

围观 13

本文针对CW32L083系列MCU,同系列产品亦可参考。

ARM® Cortex®-M0+ 内核的嵌套向量中断控制器 (NVIC),用于管理中断和异常。NVIC和处理器内核紧密相连,可以实现低延迟的异常和中断处理。处理器支持最多32个中断请求 (IRQ)输入,支持多个内部异常。

主要特性 

• 16个内部异常 

• 32个可屏蔽外部中断 

• 4个可编程的优先级 

• 低延时的异常和中断处理

• 支持中断嵌套 

• 中断向量表重映射

本文介绍了处理器的 32 个外部中断请求(IRQ0 ~ IRQ31),处理器内部异常的具体情况请参考“ARM® Cortex®-M0+Technical Reference Manual”与“ARM® v6-M Architecture Reference Manual”。

中断优先级 

外部中断可设置 4 级优先级,最高优先级为“0”,最低优先级为“3”,默认值为“0”。当处理器正在执行一个中断处理程序时,如果出现一个更高优先级的中断,那么这个中断就被抢占。如果出现的中断的优先级和正在处理的中断的优先级相同或更低,这个中断就不会被抢占,但是新中断的状态就变为挂起。如果多个挂起的中断具有相同的优先级,中断编号越小的挂起中断优先处理。例如,如果IRQ[0]和IRQ[1]均挂起时,并且两者的优先级相同,那么先处理 IRQ[0]。

中断向量表

ARM® Cortex®-M0+ 响应中断时,处理器自动从存储器的中断向量表中取出中断服务程序 ( ISR )的起始地址。中断向量表包括主栈指针(MSP)的初始值,内部异常和外部中断的服务程序入口地址。每个中断向量占用1个字(4 字节),中断向量的存储地址为向量编号乘以4,下面的是CW32L083的中断向量表。

1.png

2.png

CW32L083由于部分外设的中断复用一个IRQ中断源,在中断服务程序中应先检查中断标志位,以确定产生中断的外设。NMI在CW32L083中未使用。HSE 、LSE 时钟信号起振失败和 LSI、LSE、HSIOSC、HSE、PLL 时钟信号稳定对应 RCC 全局中断。HSE 或 LSE 时钟信号在运行中失效对应 FAULT 中断。

中断寄存器的相关配置

1.中断的使能、挂起、清除挂起

ARM® Cortex-M0+处理器支持最多32个外部中断源,分别对应中断使能设置寄存器NIVC_ISER的32个使能位,和中断使能清除寄存器NVIC_ICER的32个禁止位。将使能位置1,允许中断;将禁止位置1,禁止中断。上文中NVIC中断使能仅针对处理器 NVIC而言,外设的中断是否使能,还受相应外设的中断控制寄存器控制。

而在中断发生的时候,如果系统正在处理相同优先级的或者更高优先级的中断,系统将不会立马的处理这个中断,而是将这个中断的状态设置为挂起,保存在中断挂起状态寄存器中,在处理器未进去此中断处理之前,如果没有手动清除挂起状态,这个状态会一直有效,等处理器进入中断处理的时候,硬件会自动清除相应的中断挂起状态。也可以通过设置中断挂起设置寄存器NVIC_ISPR的对应位,将此中断的状态设置为挂起状态,如果系统没有正在处理与之相同优先级或更高优先级的中断,此中断将被立即响应并处理。可以通过设置中断挂起清除寄存器NVIC_ICPR的对应位,将此中断的状态设置为挂起清除状态。

2.中断的优先级、中断屏蔽

中断优先级控制寄存器NVIC_IPR0 ~ NVIC_IPR7,用于设置IRQ0~IRQ31 的中断优先级,每个中断源使用8位,在CW32L083中仅使用了高两位,最多可设置4个中断优先级。

在某些特殊场合,需要禁止所有中断,可以使用中断屏蔽寄存器PRIMASK实现。PRIMASK只有最低1位有效,将此位置1,除了NMI和硬件错误异常之外的所有外部中断和异常都被禁止;清0后,允许响应中断和异常。该位复位后默认为0。

按键中断检测实验分析

以CW32L083评估板为例,按键连接至CW32L083的PA4、PA5端口,LED连接至PC2、PC3接口。按键按下将产生中断,在中断服务程序中进行LED翻转。

int32_t main(void)

{

     GPIO_InitTypeDef GPIO_InitStruct = {0};

     __RCC_GPIOA_CLK_ENABLE();    // 使能GPIOA的配置时钟

     __RCC_GPIOC_CLK_ENABLE();    // 使能GPIOC的配置时钟

     //按键GPIO初始化

     GPIO_InitStruct.IT = GPIO_IT_RISING | GPIO_IT_FALLING;

     GPIO_InitStruct.Mode = GPIO_MODE_INPUT;

     GPIO_InitStruct.Pins =GPIO_PIN_4 | GPIO_PIN_5;

     GPIO_Init(CW_GPIOA, &GPIO_InitStruct);

     //LED的GPIO初始化

     GPIO_InitStruct.IT = GPIO_IT_NONE;

     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

     GPIO_InitStruct.Pins =GPIO_PIN_2 | GPIO_PIN_3;

     GPIO_Init(CW_GPIOC, &GPIO_InitStruct);

     //配置中断滤波

     GPIO_ConfigFilter(CW_GPIOA, bv4, GPIO_FLTCLK_RC150K);

     //清除PA4、PA5中断标志并使能NVIC

     GPIOA_INTFLAG_CLR(bv4| bv5);

     NVIC_EnableIRQ(GPIOA_IRQn);

     __enable_irq();

     //----------------------------------------------------------------------

     //相关程序在中断服务GPIOA_IRQHandler中进行处理

     while (1)

     {

     }

}

//GPIOA的中断服务函数

void GPIOA_IRQHandlerCallback(void)

{

    if (CW_GPIOA->ISR_f.PIN4)

    {
       GPIOA_INTFLAG_CLR(bv4);清除PA04的中断标志位

       PC03_TOG();
     }

    if (CW_GPIOA->ISR_f.PIN5)

    {
       GPIOA_INTFLAG_CLR(bv5);//清除PA05的中断标志位

       PC02_TOG();
    }
}

由上面代码可以看到,如果按下KEY1(PA04),LED1(PC03)的状态会翻转,如果松开按键,LED1又会翻转一次。在每次执行中断函数的时候,需要清除中断标志位即GPIOA_INTFLAG_CLR(bv4)。

来源:武汉芯源半导体

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

围观 30

MCU中的HSIOSC和LSI时钟信号是通过内部RC振荡器产生的,该时钟信号可能会受到外界因素比如温度等的影响,使其频率在一定范围内产生误差。CW32L083可以通过AUTOTRIM的时钟校准定时器模式来对LSI和HSIOSC进行自动实时时钟校准,获得精度更高的时钟信号。

HSIOSC时钟校准模式

设置 AUTOTRIM_CR.MD 为 0x00,使定时器工作于 HSIOSC 校准模式。该模式支持自动实时校准HSIOSC的输出频率,使 HSIOSC 输出频率的精度不再受环境变化影响。

HSIOSC 时钟校准,需要向定时器提供一个精准的低频参考时钟,其来源可以是 LSE 或外部 ETR 引脚输入的低速精准时钟信号,通过控制寄存器 AUTOTRIM_CR 的 SRC 位域进行选择。

HSIOSC 校准模式的功能框图如下图所示:

“CW32L083如何实现AUTOTRIM时钟校准?"

设置 AUTOTRIM_CR.AUTO 为 1 使能自动校准,设置 AUTOTRIM_CR.EN 为1 使能定时器,开始自动校准流程。自动校准开始工作后,计数值寄存器AUTOTRIM_CNT 在每个 GCLK 时钟周期内对 HSIOSC 时钟 TCLK 从重载值 ARR 开始递减计数,计数到 0 后开始递增计数。当计数器已运行 1.5 倍 ARR 周期,计数器停止运行,同时 AUTOTRIM_ISR.MISS 标志位被硬件置 1,表示计数失败。每当 GCLK 时钟上升沿到达时,计数器重新开始从 ARR 递减计数。

如果 GCLK 时钟周期内,计数器的计数值大于误差允许值 AUTOTRIM_FLIM,寄存器TrimCode 会自动调整,直到计数器的计数值小于误差允许值 AUTOTRIM_FLIM,同时 AUTOTRIM_ISR.OK 标志位会被硬件置 1,表示校准精度已达标,此时可读取 TrimCode 寄存器并写入 SYSCTRL_HSI.TRIM,以校准 HSIOSC 时钟频率。

TrimCode 寄存器最大可调整为 0x1FF,故 TrimCode 值写入 SYSCTRL_HSI.TRIM 时,需根据 TRIM 位域的初始校 准值写入最高 2bit。代码示例如下:

CW_SYSCTRL->HSI = (CW_SYSCTRL->HSI & 0xFE00) | CW_AUTOTRIM->TVAL;

误差允许值 FLIM 在设置重载值 ARR 时自动配置,校准精度为 0.4%,用户不可写入。重载寄存器 AUTOTRIM_ARR 设置公式如下:

ARR = TCLK×2PRS/RCLK-1

其中,RCLK 为参考时钟源,PRS 为预分频系数,TCLK 为计数时钟源 HSIOSC 时钟,这一部分是需要我们去配置的。

例:当参考时钟源 RCLK 为 LSE(时钟频率为 32768Hz),预分频系数 PRS 为 0x1 时,校准 HSIOSC 时钟频率为 48MHz,计算

ARR = 48000000×21 /32768-1 = 2928.6875

最接近的整数是:2929(0xB71)

即需要设置 AUTOTRIM_ARR 为 0xB71。

HSIOSC时钟校准编程示例

通过上节的模式设置介绍我们可以根据其配置AUTOTRIM的HSIOSC的实时时钟校准模式,HSIOSC 时钟校准流程如下,当选择参考时钟源为 LSE 时,步骤 1 和步骤 2 不需要执行:

步骤 1:设置外设时钟使能控制寄存器 SYSCTRL_AHBEN 的相关位为 1,使能AUTOTRIM_ETR 对应 GPIO 端口的配置时钟及工作时钟;

步骤 2:设置 GPIO 复用功能寄存器 GPIOx_AFRH 和 GPIOx_AFRL 的相关位,配置对应引脚为 AUTOTRIM 定时器的 AUTOTRIM_ETR 功能;

步骤 3:设置外设时钟使能控制寄存器 SYSCTRL_APBEN2.AUTOTRIM 为 1,打开 AUTOTRIM 模块的配置时钟;

步骤 4:设置 AUTOTRIM_CR.MD 为 0x00,使定时器工作于 HSIOSC 时钟校准模式;

步骤 5:配置控制寄存器 AUTOTRIM_CR.OST,选择实时校准模式或单次校准模式;

步骤 6:配置控制寄存器 AUTOTRIM_CR.SRC,选择 AUTOTRIM 参考时钟源为LSE;

步骤 7:配置控制寄存器 AUTOTRIM_CR.PRS,选择 AUTOTRIM 参考时钟分频系数;

步骤 8:根据上节HSIOSC时钟校准模式ARR 配置公式,设置重载值寄存器 AUTOTRIM_ARR,自动配置 校准精度为 0.4%;

步骤 9:设置 AUTOTRIM_CR.AUTO 为 1,使能自动校准;

步骤 10:设置 AUTOTRIM_CR.EN 为 1,使能定时器,开始自动校准;

步骤 11:查询等待 AUTOTRIM_ISR.END 和 AUTOTRIM_ISR.OK 标志位置 1,自动校准完成且精度达标;

步骤 12:读取 TrimCode 寄存器,并将 TrimCode 值写入 SYSCTRL_HSI.TRIM。

代码示例:

CW_SYSCTRL->HSI = (CW_SYSCTRL->HSI & 0xFE00) | CW_AUTOTRIM->TVAL;

具体的寄存器配置可以参考CW32L083用户手册的时钟校准定时器(AUTOTRIM)章节。在上述的一系列校准步骤配置完之后,我们就可以通过示波器或者万用表来读取开发板的HSIOSC的频率输出,会发现在不同的温度影响下,MCU会自动校准HSIOSC的时钟频率。通过对比会发现,用AUTOTRIM自动校准模式之后的HSIOSC会比没有用AUTOTRIM的HSIOSC的精度更高,误差更小。

LSI时钟校准

设置 AUTOTRIM_CR.MD 为 0x01,使定时器工作于 LSI 校准模式。该模式支持自动实时校准 LSI 的输出频率,使 LSI 输出频率的精度不再受环境变化影响。

LSI 时钟校准,需要向定时器提供一个精准的高频计数时钟,其来源可以是 HSE 或外部 ETR 引脚输入的高速精准时钟信号,通过控制寄存器 AUTOTRIM_CR 的 SRC 位域进行选择。

LSI校准模式的功能框图如下图所示:

“CW32L083如何实现AUTOTRIM时钟校准?"

设置 AUTOTRIM_CR.AUTO 为 1 使能自动校准,设置 AUTOTRIM_CR.EN 为 1 使能定时器,开始自动校准流程。

自动校准开始工作后,计数值寄存器 AUTOTRIM_CNT 在每个 GCLK 时钟周期内对计数时钟 TCLK 从重载值 ARR 开始递减计数,计数到0后开始递增计数。当计数器已运行1.5倍ARR 周期,计数器停止运行,同时 AUTOTRIM_ISR.MISS 标志位被硬件置1,表示计数失败。每当 GCLK 时钟上升沿到达时,计数器重新开始从 ARR 递减计数。

如果 GCLK 时钟周期内,计数器的计数值大于误差允许值 AUTOTRIM_FLIM,则寄存器TrimCode会自动调整,直到计数器的计数值小于误差允许值 AUTOTRIM_FLIM,同时 AUTOTRIM_ISR.OK 标志位会被硬件置 1,表示校准精度 已达标,此时可读取 TrimCode 寄存器并写入 SYSCTRL_LSI.TRIM,以校准 LSI 时钟频率。具体的代码配置可以参考下节的步骤12的代码示例。

TrimCode 寄存器最大可调整为0x1FF,故 TrimCode 值写入 SYSCTRL_LSI.TRIM 时,需根据 TRIM 位域的初始校 准值写入最高 1bit。

代码示例如下:

CW_SYSCTRL->LSI = (CW_SYSCTRL->LSI & 0xFE00) | CW_AUTOTRIM->TVAL;

误差允许值 FLIM 在设置重载值 ARR 时自动配置,校准精度为 0.4%,用户不可写入。重载寄存器 AUTOTRIM_ARR 设置公式如下:

ARR = TCLK×2PRS/RCLK-1

其中,RCLK 为 LSI 时钟,PRS 为预分频系数,TCLK 为计数时钟源。

例:当计数时钟源 TCLK 为 HSE(时钟频率为 16MHz),预分频系数 PRS 为 0x1 时,校准 LSI 时钟频率为 32kHz,计算

ARR = 16000000×21 /32000-1 = 999

即需要设置 AUTOTRIM_ARR 为 0x3E7。

LSI时钟校准编程示例

通过上节的模式设置介绍我们可以根据其配置AUTOTRIM的LSI的实时时钟校准模式,LSI 时钟校准流程如下,当选择计数时钟源为 HSE 时,步骤 1 和步骤 2 不需要执行:

步骤 1:设置外设时钟使能控制寄存器 SYSCTRL_AHBEN 的相关位为 1,使能 AUTOTRIM_ETR 对应 GPIO 端口的 配置时钟及工作时钟;

步骤 2:设置 GPIO 复用功能寄存器 GPIOx_AFRH 和 GPIOx_AFRL 的相关位,配置对应引脚为 AUTOTRIM 定时器 的 AUTOTRIM_ETR 功能;

步骤 3:设置外设时钟使能控制寄存器 SYSCTRL_APBEN2.AUTOTRIM 为 1,打开 AUTOTRIM 模块的配置时钟;

步骤 4:设置 AUTOTRIM_CR.MD 为 0x01,使定时器工作于 LSI 时钟校准模式;

步骤 5:配置控制寄存器 AUTOTRIM_CR.OST,选择实时校准模式或单次校准模式;

步骤 6:配置控制寄存器 AUTOTRIM_CR.SRC,选择 AUTOTRIM 计数时钟源HSE;

步骤 7:配置控制寄存器 AUTOTRIM_CR.PRS,选择 AUTOTRIM 参考时钟分频系数;

步骤 8:根据 11.3.3 LSI 时钟校准小节 ARR 配置公式,设置重载值寄存器 AUTOTRIM_ARR,自动配置校准精度 为 0.4%;

步骤 9:设置 AUTOTRIM_CR.AUTO 为 1,使能自动校准;

步骤 10:设置 AUTOTRIM_CR.EN 为 1,使能定时器,开始自动校准;

步骤 11:查询等待 AUTOTRIM_ISR.END 和 AUTOTRIM_ISR.OK 标志位置 1,自动校准完成且精度达标;

步骤 12:读取 TrimCode 寄存器,并将 TrimCode 值写入 SYSCTRL_LSI.TRIM。

代码示例:

CW_SYSCTRL->LSI = (CW_SYSCTRL->LSI & 0xFE00) | CW_AUTOTRIM->TVAL

更多详细信息,请访问武汉芯源官方网站:https://www.whxy.com

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

围观 35
订阅 RSS - CW32L083