上一期文章,我們講了基于STM32的抗干擾方法:增加硬件失效時軟件復位及看門狗功能。這期我們將介紹基于CW32 的抗干擾問題。
在1、2期文章和視頻中(可進入”MCU研究實驗室”公眾號查看原文),為了公平起見,所有的MCU使用的是同一個工程程序,(不同的MCU,時鐘和GPIO的配置略有不同,使用宏定義區分MCU),除了使用滴答時鐘和基本GPIO操作外,沒有任何抗干擾手段,全靠MCU內部自身的抗干擾能力進行的測試。結果,只有芯源CW32 MCU沒有徹底死機外,其它均有死機現象。
這種死機現象,在我們實際開發產品時,是禁止發生的。為了對付這種干擾,除了硬件上有些技術對策,那軟件上又有些什么呢?
當然是我們最熟悉的看門狗了。“看門狗”這個神器在“古老的年代”51時期,那是沒有的,需要在外面加一個“昂貴”的芯片來實現。當然,現在新時代,所有的ARM MCU基本上都標配了看門狗外設。
CW32在抗干擾測試時,也偶有自身復位現象。當然如果我們增加了看門狗抗干擾技術,那設計出來的產品不是更穩定嗎!
看門狗是啥呢,我們來看一下,CW32芯片的用戶手冊,關于看門狗的介紹。
這里我們就不詳細展開其內容了。直接來看核心代碼:
//系統時鐘配置為48M HSI倍數 #include "main.h" #include "cw32f030_gpio.h" //GPIOA端口 #define SEGA GPIO_PIN_10 #define SEGB GPIO_PIN_9 #define SEGC GPIO_PIN_8 //GPIOB端口 #define SEGD GPIO_PIN_14 #define SEGE GPIO_PIN_15 //GPIOA端口 #define SEGF GPIO_PIN_11 #define SEGG GPIO_PIN_12 //GPIOB端口 #define SEGDP GPIO_PIN_13 //num:需要顯示的數字,no:0顯示左邊數碼管,1顯示右邊數碼管 void SEG_DisplayNum(unsigned int num, unsigned int no) { GPIO_WritePin(CW_GPIOA,0xffff,GPIO_Pin_RESET);//關段碼、位碼 GPIO_WritePin(CW_GPIOB,0xffff,GPIO_Pin_RESET);// switch(num) //開斷碼 { case 0: //ABCDEF GPIO_WritePin(CW_GPIOA,SEGA|SEGB|SEGC|SEGF,GPIO_Pin_SET); GPIO_WritePin(CW_GPIOB,SEGD|SEGE,GPIO_Pin_SET); break; case 1: //BC GPIO_WritePin(CW_GPIOA,SEGB|SEGC,GPIO_Pin_SET); break; case 2: //ABDEG GPIO_WritePin(CW_GPIOA,SEGA|SEGB|SEGG,GPIO_Pin_SET); GPIO_WritePin(CW_GPIOB,SEGD|SEGE,GPIO_Pin_SET); break; case 3: //ABCDG GPIO_WritePin(CW_GPIOA,SEGA|SEGB|SEGC|SEGG,GPIO_Pin_SET); GPIO_WritePin(CW_GPIOB,SEGD,GPIO_Pin_SET); break; case 4://BCFG GPIO_WritePin(CW_GPIOA,SEGF|SEGB|SEGC|SEGG,GPIO_Pin_SET); break; case 5://ACDFG GPIO_WritePin(CW_GPIOA,SEGA|SEGC|SEGG|SEGF,GPIO_Pin_SET); GPIO_WritePin(CW_GPIOB,SEGD,GPIO_Pin_SET); break; case 6: //ACDEFG GPIO_WritePin(CW_GPIOA,SEGA|SEGC|SEGG|SEGF,GPIO_Pin_SET); GPIO_WritePin(CW_GPIOB,SEGD|SEGE,GPIO_Pin_SET); break; case 7: //ABC GPIO_WritePin(CW_GPIOA,SEGA|SEGB|SEGC,GPIO_Pin_SET); break; case 8: //ABCDEFG GPIO_WritePin(CW_GPIOA,SEGA|SEGB|SEGC|SEGG|SEGF,GPIO_Pin_SET); GPIO_WritePin(CW_GPIOB,SEGD|SEGE,GPIO_Pin_SET); break; case 9: //ABCDFG GPIO_WritePin(CW_GPIOA,SEGA|SEGB|SEGC|SEGG|SEGF,GPIO_Pin_SET); GPIO_WritePin(CW_GPIOB,SEGD,GPIO_Pin_SET); break; case 10: //DP 顯示DP GPIO_WritePin(CW_GPIOB,SEGDP,GPIO_Pin_SET); break; default: break; } if(no==1) PB12_SETHIGH();//開位碼 else PB11_SETHIGH();//開位碼 } void RCC_Configuration(void) { /* 0. HSI使能并校準 */ RCC_HSI_Enable(RCC_HSIOSC_DIV6); /* 1. 設置HCLK和PCLK的分頻系數*/ RCC_HCLKPRS_Config(RCC_HCLK_DIV1); RCC_PCLKPRS_Config(RCC_PCLK_DIV1); /* 2. 使能PLL,通過PLL倍頻到64MHz */ RCC_PLL_Enable(RCC_PLLSOURCE_HSI, 8000000, 6); // HSI 默認輸出頻率8MHz __RCC_FLASH_CLK_ENABLE(); FLASH_SetLatency(FLASH_Latency_3); /* 3. 時鐘切換到PLL */ RCC_SysClk_Switch(RCC_SYSCLKSRC_PLL); RCC_SystemCoreClockUpdate(48000000); } void GPIOInit(void) { GPIO_InitTypeDef GPIO_InitStruct; __RCC_GPIOB_CLK_ENABLE(); __RCC_GPIOA_CLK_ENABLE(); //數碼管斷碼位碼 IO初始化 GPIO_InitStruct.IT = GPIO_IT_NONE; //LED1 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pins = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_Init(CW_GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pins = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_Init(CW_GPIOB, &GPIO_InitStruct); } int main() { unsigned long i; unsigned int num=0; IWDT_InitTypeDef IWDT_InitStruct = {0}; for(i=0;i<60000;i++); //上電延時 RCC_Configuration(); //時鐘配置 GPIOInit(); //數碼管GPIO初始化 //使用獨立看門狗功能 CW_SYSCTRL->APBEN1_f.IWDT = 1U; //使能IWDT模塊 IWDT_InitStruct.IWDT_ITState = ENABLE; IWDT_InitStruct.IWDT_OverFlowAction = IWDT_OVERFLOW_ACTION_INT; //溢出后產生中斷不復位 IWDT_InitStruct.IWDT_Pause = IWDT_SLEEP_PAUSE; IWDT_InitStruct.IWDT_Prescaler = IWDT_Prescaler_DIV4; IWDT_InitStruct.IWDT_ReloadValue = (IWDT_FREQ >> 2) / 1000 * 280 - 1; // 由于IWDT的時鐘為RC10K, 設置為280實際溢出時間為256ms左右 IWDT_InitStruct.IWDT_WindowValue = 0xFFF; IWDT_Init(&IWDT_InitStruct); IWDT_Cmd(); __disable_irq(); NVIC_EnableIRQ(WDT_IRQn); __enable_irq(); while(1) { num++; //一個循環,數據加1 if(num>=100)num=0; //限數0-99 SEG_DisplayNum(num/10,0); //顯示數據十位 for(i=0;i<60000;i++); //延時 SEG_DisplayNum(num%10,1); //顯示數據個位 for(i=0;i<60000;i++); //延時 IWDT_Refresh(); //喂狗 SEG_DisplayNum(num/10,0); //顯示數據十位 for(i=0;i<60000;i++); //延時 IWDT_Refresh(); //喂狗 SEG_DisplayNum(num%10,1); //顯示數據個位 for(i=0;i<60000;i++); //延時 SEG_DisplayNum(num/10,0); //顯示數據十位 for(i=0;i<60000;i++); //延時 IWDT_Refresh(); //喂狗 SEG_DisplayNum(num%10,1); //顯示數據個位 for(i=0;i<60000;i++); //延時 IWDT_Refresh(); //喂狗 } } //CW32看門狗中斷函數 void WDT_IRQHandler(void) { unsigned int j; if(CW_IWDT->SR & IWDT_SR_OV_Msk) { //獨立看門狗溢出發生 IWDT_ClearOVFlag(); /*清除標志 */ while (1) { SEG_DisplayNum(10,1); //顯示右測數碼管的小數點位 for(j=0;j<60000;j++); for(j=0;j<60000;j++); for(j=0;j<60000;j++); for(j=0;j<60000;j++); for(j=0;j<60000;j++); for(j=0;j<60000;j++); __NVIC_SystemReset(); //軟件復位,系統重新運行。 } } }
這里的代碼與1、2期代碼不同,我們使用官方標準庫來重新編寫。其中數碼管的動態掃描沒有使用滴答時鐘,而是在主程序中直接用延時來完成。區別于之前的代碼,我們增加了獨立看門狗的功能。看門狗的喂狗操作在MAIN函數的大循環里,數碼管的動態掃描中實現。
當程序發生死機時,MAIN函數的大循環將暫停運行,數碼管隨機顯示最近一次數值,不進行動態掃描,所以,只有一位數碼管顯示。同時,喂狗暫停。
看門狗的代碼配置為產生中斷不復位。與STM32不同,看門狗可以停止復位,先進中斷。因此,當看門狗時間到,進入看門狗中斷函數WDT_IRQHandler()中,在中斷函數中,將右則數碼管小數點顯示出來,并進行軟件復位。這樣通過小數點顯示再判斷看門狗事件的發生。
除了看門狗復位,還有一種軟件復位方式。當MCU發生硬件失效時,會進入Hardfault中數函數。Hardfault是優先級別為-1的固定類型中斷,無需初始化設置。常常在MCU死機時,不知明的會進入Hardfault中斷。因此,在Hardfault中斷函數中,添加軟件復位功能也是一種防死機現象的方法。
Hardfault中斷函數中代碼如下:
void HardFault_Handler(void) { /* USER CODE BEGIN HardFault_IRQn */ unsigned int j; /* USER CODE END HardFault_IRQn */ while (1) { /* USER CODE BEGIN W1_HardFault_IRQn */ while (1) { SEG_DisplayNum(10,0); for(j=0;j<60000;j++); for(j=0;j<60000;j++); for(j=0;j<60000;j++); for(j=0;j<60000;j++); for(j=0;j<60000;j++); for(j=0;j<60000;j++); __NVIC_SystemReset(); } /* USER CODE END W1_HardFault_IRQn */ } }
34這就是CW32關于看門狗的一個介紹。
CW32芯片本身在內部設計的時候充分考慮了各種ESD抗干擾手段,所以即使軟件上不加任何軟件抗干擾處理,它自身已經有比較強的抗干擾能力了。然后,所以我們做實驗的結果,沒有STM32那么明顯,就是加看門狗和不加看門狗都沒那么明顯,它本身就可以扛得住各種干擾了。
但是,一個規范性的程序,一個可靠性的軟硬設計都非常重要。建議用戶在產品開發的時候,還是應該把看門狗功能加上去。因為外面可能有雷擊,有各種電網的波動,各種意外。那么當意外發生的時候,MCU不能死機,但可以復位,可以重新運行,不能死鎖。所以我們要養成良好的編程習慣,養成良好的產品設計思維,要把我們抗干擾這個手段加上去,這也是我們給大家一直來做這個抗干擾實驗的一個目的和意義所在。
審核編輯:湯梓紅
-
單片機
+關注
關注
6035文章
44554瀏覽量
634641 -
mcu
+關注
關注
146文章
17123瀏覽量
350990 -
看門狗
+關注
關注
10文章
560瀏覽量
70789 -
抗干擾
+關注
關注
4文章
316瀏覽量
34573 -
GPIO
+關注
關注
16文章
1204瀏覽量
52052 -
CW32
+關注
關注
1文章
203瀏覽量
626 -
武漢芯源
+關注
關注
1文章
66瀏覽量
253
發布評論請先 登錄
相關推薦
評論