天天看點

STM8S---選項位元組(Option Byte)寫操作之IO複用

功能實作目标

  通過對選項位元組的寫操作來實作TIM2的CH3通道的PWM輸出IO複用。能夠設定為PA3或者PD2輸出。

通過STVP方式操作連結

選項位元組

  選項位元組包含晶片硬體特性的配置和存儲器的保護資訊,這些位元組儲存在存儲器中一個專用的塊内。除了ROP(讀出保護)位元組,每一個選項位元組必須被儲存兩次。一個是通常的格式(OPTx)和一個用來備份互補格式的(NOPTx)。選項位元組能夠通過應用程式在IAP模式下改動,可是ROP選項僅僅能在ICP模式(通過SWIM)下被改動。

有關SWIM程式設計過程的内容能夠參考STM8S閃存程式設計手冊(PM0051)和STM8 SWIM通信協定和調試子產品使用者手冊(UM0470)。

  不同的晶片的選項位元組大小不一樣,詳細的能夠參考晶片資料手冊。如用STM8S103F3來舉例。選項位元組例如以下:

STM8S---選項位元組(Option Byte)寫操作之IO複用
  STM8S103F對于20腳封裝的産品的複用功能重定義位:
STM8S---選項位元組(Option Byte)寫操作之IO複用

  由此可知我們要将OPT2位元組中的AFR1位進行寫操作,通過寫0。則portA3複用功能TIM2_CH3,通過寫1,portD2複用功能TIM2_CH3。

接下來通過程式實作這個功能,能夠改動AFR1的值來看PWM輸出是否切換了管腳。假設能,則是實作了寫操作。

  選項位元組存放在EEPROM中,是以能夠通過讀寫EEPROM一樣的操作方式來改動選項位元組。應用程式能夠直接向目标位址進行寫操作。位址從上面的圖中我們已經知道了:0x4803,0x4804。寄存器的配置能夠查閱參考手冊(RM0016)。

  相關寄存器操作:

STM8S---選項位元組(Option Byte)寫操作之IO複用
STM8S---選項位元組(Option Byte)寫操作之IO複用

測試程式實作

  注意:實作程式擦寫Option Bytes時,不能執行應用程式,否則會出現錯誤!隻是還是認為這點麻煩啊。還不如用STVP來擦寫,要是能夠放在應用程式中共存來擦寫就好了,用程式實作複用就這麼麻煩嗎?希望能探索找到好的方法,最後僅僅找到了個不靠譜的。就是在擦寫後加上延時。可是這個時管用時無論用。還是再查閱資料看看是怎麼回事?

STM8S---選項位元組(Option Byte)寫操作之IO複用
  可是用STVP擦寫時又遇到了這個錯誤:

Error : Error on Option Bytes (complementary bytes). Reprogram Option Bytes of device     Error : < OPTION BYTE verifying failed.           

  用STVP來擦寫Option Bytes了。先将ROP設定為ON,然後再擦寫Option Bytes,會出現兩個提示框,選擇是(Y)。再之後又将ROP設定為OFF,再次擦寫Option Bytes,則又能夠用STVD通過stlink來燒敲代碼并仿真了。

STM8S---選項位元組(Option Byte)寫操作之IO複用
STM8S---選項位元組(Option Byte)寫操作之IO複用
STM8S---選項位元組(Option Byte)寫操作之IO複用
測試程式:           
/* MAIN.C file     Functons    :   操作option byte位元組,設定IO複用,來改動TIM2的CH3通道PWM輸出管腳PA3 or PD2     Date        :   2015年7月22日     Author      :   yicm     Notes       :         */     #include<stm8s003f3p.h>     void CLK_init(void)     {         CLK_ICKR |= 0X01;           //使能内部快速時鐘 HSI         CLK_CKDIVR = 0x08;          //16M内部RC經2分頻後系統時鐘為8M         while(!(CLK_ICKR&0x02));    //HSI準備就緒          CLK_SWR=0xe1;               //HSI為主時鐘源      }     void Init_GPIO(void)     {         /*設定為推挽輸出,PD2接了LED燈*/         PD_DDR |= 0X04;             //設定PD2port為輸出模式         PD_CR1 |= 0X04;             //設定PD2port為推挽輸出模式         PD_CR2 &= 0XFD;         PA_DDR |= 0X08;             //設定PA3port為輸出模式         PA_CR1 |= 0X08;             //設定PA3port為推挽輸出模式         PA_CR2 |= 0XF7;     }     void Init_Tim2(void)     {         TIM2_CCMR3 |=   0X70;   //設定定時器2三通道(PD2)輸出比較三模式         TIM2_CCMR3 |= 0X04;     //輸出比較3預裝載使能         TIM2_CCER2 |= 0x03;     //通道3使能,低電平有效,配置為輸出         // 初始化時鐘分頻器為1,即計數器的時鐘頻率為Fmaster=8M/64=0.125MHZ         TIM2_PSCR = 0X07;            //初始化自己主動裝載寄存器,決定PWM 方波的頻率。Fpwm=0.125M/62500=2HZ         TIM2_ARRH = 62500/256;         TIM2_ARRL = 62500%256;         //初始化比較寄存器。決定PWM 方波的占空比:5000/10000 = 50%         TIM2_CCR3H = 31250/256;         TIM2_CCR3L = 31250%256;         //啟動計數;更新中斷失能         TIM2_CR1 |= 0x81;         //TIM2_IER |= 0x00;             }     void Write_Option_Byte(void)     {            unsigned char opt[6] = {0,0,0x00,0,0,0};         /*解鎖Flash*/         do         {             FLASH_DUKR = 0xAE;             FLASH_DUKR = 0x56;               }         while(!(FLASH_IAPSR & 0X08));         /*對選項位元組進行寫操作使能*/         FLASH_CR2 = 0X80;         /*互補控制寄存器*/         FLASH_NCR2 = 0X7F;         /*寫操作,0x02:PD2。0x00:PA3*/         *((unsigned char *)0x4800) = opt[0];         *((unsigned char *)0x4801) = opt[1];         *((unsigned char *)0x4802) = ~opt[1];         *((unsigned char *)0x4803) = opt[2];         *((unsigned char *)0x4804) = ~opt[2];         *((unsigned char *)0x4805) = opt[3];         *((unsigned char *)0x4806) = ~opt[3];         *((unsigned char *)0x4807) = opt[4];         *((unsigned char *)0x4808) = ~opt[0];         *((unsigned char *)0x4809) = opt[5];         *((unsigned char *)0x480A) = ~opt[5];           /*等待寫結束*/         while(!(FLASH_IAPSR & 0x04));     }     main()     {         int i;         Write_Option_Byte();    //執行程式時,屏蔽           for(i=0;i<10000;++i);   //延時效果,有時加上延時,能夠使擦寫和應用程式同一時候不屏蔽也能管用         CLK_init();             //擦寫時屏蔽。否則下次stlink仿真時會出錯         Init_GPIO();            //擦寫時屏蔽,否則下次stlink仿真時會出錯         Init_Tim2();            //擦寫時屏蔽,否則下次stlink仿真時會出錯         while (1);     }           

繼續閱讀