c语言stm8变量存储类型,STM8S---选项字节(Option Byte)写操作之IO复用

功能实现目标

通过对选项字节的写操作来实现TIM2的CH3通道的PWM输出IO复用。能够设置为PA3或者PD2输出。

选项字节

选项字节包含芯片硬件特性的配置和存储器的保护信息,这些字节保存在存储器中一个专用的块内。除了ROP(读出保护)字节,每一个选项字节必须被保存两次。一个是通常的格式(OPTx)和一个用来备份互补格式的(NOPTx)。选项字节能够通过应用程序在IAP模式下改动,可是ROP选项仅仅能在ICP模式(通过SWIM)下被改动。

有关SWIM编程过程的内容能够參考STM8S闪存编程手冊(PM0051)和STM8 SWIM通信协议和调试模块用户手冊(UM0470)。

不同的芯片的选项字节大小不一样,详细的能够參考芯片数据手冊。如用STM8S103F3来举例。选项字节例如以下:

a789990936b93eade8e438d4613c699eda4.jpg

STM8S103F对于20脚封装的产品的复用功能重定义位:

049887bcaf917f75124902b2ea238fb0a84.jpg

由此可知我们要将OPT2字节中的AFR1位进行写操作,通过写0。则portA3复用功能TIM2_CH3,通过写1,portD2复用功能TIM2_CH3。

接下来通过程序实现这个功能,能够改动AFR1的值来看PWM输出是否切换了管脚。假设能,则是实现了写操作。

选项字节存放在EEPROM中,所以能够通过读写EEPROM一样的操作方式来改动选项字节。应用程序能够直接向目标地址进行写操作。地址从上面的图中我们已经知道了:0x4803,0x4804。寄存器的配置能够查阅參考手冊(RM0016)。

相关寄存器操作:

b6b5e2948ccfbdf3ec4b372ad53f72f3bf2.jpg

4a793142d011a59ea8a627df9f75509bd87.jpg

測试程序实现

注意:实现程序擦写Option Bytes时,不能执行应用程序,否则会出现错误!只是还是认为这点麻烦啊。还不如用STVP来擦写,要是能够放在应用程序中共存来擦写就好了,用程序实现复用就这么麻烦吗?希望能探索找到好的方法,最后仅仅找到了个不靠谱的。就是在擦写后加上延时。可是这个时管用时无论用。还是再查阅资料看看是怎么回事?

31c159b4ba9b657bb903bb41eb231f54738.jpg

可是用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来烧敲代码并仿真了。

c2a43f1fa8df68843449ab829db9b0dda6d.jpg

0fbb3835c999141622e26680b23ef6f352b.jpg

14e22d3c9a9f7da74c4448228909fe68851.jpg

測试程序:

/* MAIN.C file

Functons : 操作option byte字节,设置IO复用,来改动TIM2的CH3通道PWM输出管脚PA3 or PD2

Date : 2015年7月22日

Author : yicm

Notes :

*/

#include

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

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值