IAR的自带例程里有这样的操作:FLASH->IAPSR &= (u8)(~FLASH_IAPSR_DUL);
而我的操作:FLASH_IAPSR_DUL=0;就报错,编译不过,我看过系统头文件,已经对FLASH_IAPSR_DUL进行了定义,所以不存在没定义的问题。
而且编译报错是Error[Pe137]: expression must be a modifiable lvalue,即指FLASH_IAPSR_DUL不可修改,这是为什么啊,一直没解决掉,后来也没管他,今天打干扰的时候出问题了……郁闷。
楼主先找本C语言的书看看,
什么是左值(lvalue),什么是右值(rvalue)。
谢谢楼上各位的回答,关于C语言的问题,左值和右值的概念我还是懂的,如果是常量宏定义,我不否认我的写法是有问题的。但是如果去IAR自带的iostm8.h的头文件中看,
#define FLASH_IAPSR_DUL FLASH_IAPSR_bit.DUL
不难发现 FLASH_IAPSR_DUL不是常量,而是结构体的成员变量,所以不会存在赋值、以及左右值的问题。
在头文件中队FLASH_IARSR的结构体定义为:
__IO_REG8_BIT(FLASH_IAPSR, 0x505F, __READ, __BITS_FLASH_IAPSR);即该寄存器为只读。
我现在唯一的解决办法是更改系统头文件,将该寄存器更改为可读可写(__READ_WRITE),才可以解决在密码开启之后的数据写保护问题。(当然单片机复位不算)
更改后的结果是:编译能通过、密钥开启后可以通过DUL清零(即重新写保护),与PDF资料相符。
还是想请权威人士给一个肯定的结论,这样的操作是不是有风险,还是IAR本身的问题?
工程使用的ST的固件库没有?
如果使用了,楼主你找错了文件。
(使用库并没有包含iostm8.h,而是包含stm8s.h)
我没有使用库,库太繁琐。直接操作寄存器,自己写的,对了我的开发环境是IAR,我看安装目录下的头文件夹内都是是io打头的头文件,LS是用的STVD吗?
/*******************************************************************************
Copyright (C), 2003-2009, winpark Electronics Co., Ltd.
Flie name: for STM8Sxxx--eeprom
Author: black.lu
Version: V1.00
Date: 2010-6-29
Description:对STM8系列单片机的内部EEPROM进行操作
*******************************************************************************/
#include "File_Include.h"
//----------------------------------------------------------
#define MASS_KEY1 0XAE //写操作密钥,注意FLASH与EEPROM的密钥相反
#define MASS_KEY2 0X56
//----------------------------------------------------------
/***********************************************************
* 函数:void STM8_EEPROM_Init(void)
* 说明:EEPROM的寄存器初始化
* 参数:无
* 输出:无
* 返回:无
***********************************************************/
void STM8_EEPROM_Init(void)
{
//都初始化为默认值
FLASH_CR1=0X00;
FLASH_CR2=0X00;
FLASH_NCR2=0XFF;
}
/***********************************************************
* 函数:void STM8_EEPROM_MASS(void)
* 说明:对STM8的EEPROM写使能和写保护
* 参数:bool mass_en
0--写保护
1--写使能
* 输出:无
* 返回:无
***********************************************************/
void STM8_EEPROM_MASS(bool mass_en)
{
if(mass_en) //写使能
{
FLASH_DUKR=MASS_KEY1;
FLASH_DUKR=MASS_KEY2;
while(!FLASH_IAPSR_DUL)asm("nop"); //等待硬件置位
}
else //写保护
{
FLASH_IAPSR_DUL=0;
}
}
/***********************************************************
* 函数:void STM8_EEPROM_Write_Byte(void)
* 说明:EEPROM写一字节函数
* 参数:uint16 address----写入数据的地址
uint8 dat----写入的一字节数据
bool mass_en----密钥开启选择
* 输出:无
* 返回:无
***********************************************************/
void STM8_EEPROM_Write_Byte(uint16 address, uint8 dat, bool mass_en)
{
if(mass_en) //是否需要密钥
{
STM8_EEPROM_MASS(1); //密钥使能
}
*((uint8 *)address)=dat; //写入地址
// STM8_EEPROM_MASS(0); //禁止写入,直接在使用时将其禁止
}
/***********************************************************
* 函数:uint8 STM8_EEPROM_Read_Byte(uint8 address)
* 说明:EEPROM读取地址一字节函数
* 参数:address----需要读取的地址
* 输出:无
* 返回:uint8
***********************************************************/
uint8 STM8_EEPROM_Read_Byte(uint16 address)
{
uint8 lc_dat_buf;
lc_dat_buf=*((uint8 *)address); //读取偏移地址数据
return lc_dat_buf;
}
/***********************************************************
* 函数:void STM8_EEPROM_Write_NByte(void)
* 说明:EEPROM写N字节函数
* 参数:uint16 address----写入数据的起始地址的地址
uint8 *p----写入的数据指针
uint8 n-----写入的个数
* 输出:无
* 返回:无
***********************************************************/
void STM8_EEPROM_Write_NByte(uint16 address, uint8 *p, uint8 n)
{
uint16 lc_adr_buf;
uint8 i;
STM8_EEPROM_MASS(1); //密钥使能
lc_adr_buf=address; //起始地址
for(i=0;i<n;i++)
{
*((uint8 *)lc_adr_buf)=*p;
lc_adr_buf++;
p++;
}
STM8_EEPROM_MASS(0); //禁止写入
}
/***********************************************************
* 函数:void STM8_EEPROM_Read_NByte(void)
* 说明:EEPROM读N字节函数
* 参数:uint16 address----读取的数据的起始偏移地址
uint8 *p----读取后存入的首地址
uint8 n-----读取的个数
* 输出:无
* 返回:无
***********************************************************/
void STM8_EEPROM_Read_NByte(uint16 address, uint8 *p, uint8 n)
{
uint16 lc_adr_buf;
uint8 i;
for(i=0;i<n;i++)
{
*p=*((uint8 *)lc_adr_buf);
p++;
lc_adr_buf++;
}
}
我的EEPROM的驱动文件部分的代码都在上面了,红色句就是编译不过的。
这个问题挺有意思
我的理解: 寄存器定义的时候类型为READ,那么这个寄存器就相当于定义了一个const修饰的常变量,是不能当左值用的。而把寄存器定义改为READ WRITE型的时候,这个寄存器就可读可写的了。
这么做有没有风险,得看STM8手册上对该寄存器的描述
今天看了一下IAREWARM,感觉昨天猜对了,io_macros.h中:
#define __READ_WRITE
#ifdef __cplusplus
#define __READ /* Not supported */
#else
#define __READ const
#endif
#define __WRITE /* Not supported */
如果按PDF上的说明,FLASH_IAPSR寄存器的DUL位是可以通过写入密钥来硬件置位,(中文手册36页,英文手册51页)软件清零的。即该位是可读可写的。
那就不太清楚了,对STM8不熟悉,很可能是这个寄存器中有其它的位是只读位,头文件中就把整个寄存器定义成只读了
自己进行些小修改,就可以了,比如:
__IO_REG8_BIT(FLASH_IAPSR_RW, 0x505F, __READ, __BITS_FLASH_IAPSR);即该寄存器为可读写。
#define FLASH_IAPSR_RW_DUL FLASH_IAPSR_RW_bit.DUL
FLASH_IAPSR_RW_DUL=0;
楼主上传最小反映问题工程。
光代码没用,无解。
这里仅仅是个编译错误,要找错误得看上下文环境。
……还有哪些错误啊,能不能举例下,免得我以后遇到又没辙,感谢!
好像TM2部分在103F3时有错误吧,还有级的少一个端口定义;记不清了,后来就用库了。