内容发布更新时间 : 2024/11/16 13:54:59星期一 下面是文章的全部内容请认真阅读。
问题一:IAR中如何做位定义,位操作 以前在STVD中,使用如下语句做位定义
_Bool L1 @PA_ODR : 6; //数码管个位, 低电平点亮 _Bool L2 @PA_ODR : 5; //数码管十位, 低电平点亮 _Bool L3 @PA_ODR : 4; //数码管百位, 低电平点亮 但是同样的语句在IAR中不能用了,编译时报错。
后来,查看IAR中的头文件 \,看到如下语句 /*------------------------------------------------------------------------- * Port A bit fields
*-----------------------------------------------------------------------*/ #ifdef __IAR_SYSTEMS_ICC__
#define PA_ODR_ODR0 PA_ODR_bit.ODR0 #define PA_ODR_ODR1 PA_ODR_bit.ODR1
想想看:既然可以用PA_ODR_ODR1来指定某个位,那么我再将某个位用define重新定义为我想要的名字不就可以了吗?心动不如行动,于是写下如下语句: #define Sound_K PA_ODR_ODR6; //语音控制K
原本以为十拿九稳,肯定能编译通过,结果现实狠狠地教训了我一下,报错! Error【Pe029】:expected an expression
我百思不得其解,以为IAR不支持这种重复定义的方式,于是换用bool,_Bool, _bool, bit ......各种方法尝试,结果均以失败告终,事情似乎走到了尽头。 最后,抱着试一试的想法,我把原头文件中的语句 #define PA_ODR_ODR6 PA_ODR_bit.ODR6 换成
#define Sound PA_ODR_ODR6 //语音控制K 结果,编译通过了,我真是泪流满面啊,没想到问题解决了。 回过头来,我再检查之前的语句
#define Sound_K PA_ODR_ODR6; //语音控制K 和后来我在IAR头文件中写下的语句
#define Sound_K PA_ODR_ODR6 //语音控制K
原来是多写了一个分号,导致编译失败。啊,我抓狂啊,基本功啊基本功,太重要了:C语言中,define语句结尾是不需要用分号的!
问题二:IAR中是否支持二进制数的使用(0B表示二进制0X表示十六进制)
二进制用后缀B(Binary),如10101111B,八进制用后缀Q(原是字母O,Octal,避免与数字0混淆)如257Q,十进制用后缀D(Decimal也可以不用后缀)如175D或175,十六进制用后缀H(Hexadecimal),如AFH等.
16进制的表示法,用字母H后缀表示,比如BH就表示16进制数11;也可以用0X前缀表示,比如0X23就是16进制的23.
以前在STVD+COSMIC的环境下,端口初始化的语句为: PA_DDR = 0B10000000;(二进制前缀)
在IAR环境中,本语句报错,于是网上到处查找,结果大多数的说法是:IAR可以支持8、10、16进制,但是不支持2进制的表达方式。哎,没办法,之后改为如下方式: PA_DDR = 0X80; //0B 1000 0000(十六进制前缀) 将原二进制数据作为注释。经过测试,编译可以通过。 问题三:中断处理
在本项目中需要用到多个中断,其中就包括定时器中断。之前在STVD环境下开发时,只要新建一个工程,系统就会自动为你添加main.c和stm8_interrupt_vector.c这两个函数,而且stm8_interrupt_vector.c函数中,已写好了很多代码,实际使用时,只需要写下自己的中断处理函数,然后将函数名复制到中断号相对应的结构体中即可被调用,部分代码如下:
@far @interrupt void Timer2 (void) {
//------ 清除中断标志
TIM2_SR1=TIM2_SR1 & 0xfe; (0xfe:唤醒命令) //------ 遥控信号计数
if(Remote1 || Remote2 || Remote3) {
Count_Remote++; if(Count_Remote>30) Count_Remote=30; }
else Count_Remote=0; }
以上是我自己编写的中断处理函数,用以实现我想要的功能。 struct interrupt_vector const _vectab[] = {
{0x82, (interrupt_handler_t)_stext}, /* reset */ {0x82, NonHandledInterrupt}, /* trap */ {0x82, NonHandledInterrupt}, /* irq0 */ {0x82, NonHandledInterrupt}, /* irq1 */ {0x82, NonHandledInterrupt}, /* irq2 */ {0x82, NonHandledInterrupt}, /* irq3 */ {0x82, NonHandledInterrupt}, /* irq4 */ {0x82, NonHandledInterrupt}, /* irq5 */ {0x82, NonHandledInterrupt}, /* irq6 */ {0x82, NonHandledInterrupt}, /* irq7 */ {0x82, NonHandledInterrupt}, /* irq8 */ {0x82, NonHandledInterrupt}, /* irq9 */ {0x82, NonHandledInterrupt}, /* irq10 */ {0x82, NonHandledInterrupt}, /* irq11 */ {0x82, NonHandledInterrupt}, /* irq12 */ {0x82, Timer2}, /* irq13 */
{0x82, NonHandledInterrupt}, /* irq14 */ {0x82, NonHandledInterrupt}, /* irq15 */ {0x82, NonHandledInterrupt}, /* irq16 */
{0x82, NonHandledInterrupt}, /* irq17 */ {0x82, NonHandledInterrupt}, /* irq18 */ {0x82, NonHandledInterrupt}, /* irq19 */ {0x82, NonHandledInterrupt}, /* irq20 */ {0x82, NonHandledInterrupt}, /* irq21 */ {0x82, NonHandledInterrupt}, /* irq22 */ {0x82, NonHandledInterrupt}, /* irq23 */ {0x82, NonHandledInterrupt}, /* irq24 */ {0x82, NonHandledInterrupt}, /* irq25 */ {0x82, NonHandledInterrupt}, /* irq26 */ {0x82, NonHandledInterrupt}, /* irq27 */ {0x82, NonHandledInterrupt}, /* irq28 */ {0x82, NonHandledInterrupt}, /* irq29 */ };
上面这些,大部分是系统自带的代码,我只做了一个很小的改动: 把我的名为“Timer2”的中断处理函数放在了/*irq13*/的位置, 也许有人会问为什么是放在这个位置?
答案很简单:因为芯片STM8的资料中,中断向量表指出:TIM2的中断号为13。 好了,以上是STVD环境下的中断函数的编写,程序也通过了编译,可以正常工作。 然后,我把这个名为“stm8_interrupt_vector.c“的函数直接添加到IAR中使用时,编译无法通过,报错了,因为,@far是STVD编译器独有的寻址方式,表示在更大的范围内寻址,具体的寻址范围我记不清了,有兴趣的朋友可以查阅相关的芯片资料。 通过查找想关资料,我把程序做了如下改动: #pragma vector = 15 //改动1,改动2 __interrupt void Timer2 (void) //改动3 {
//------ 清除中断标志
TIM2_SR1=TIM2_SR1 & 0xfe;
//------
//此处省略其它代码 }
以上共有3处改动,
改动1:用关键字#pragma vector=指出本中断处理函数指向的中断号
改动2:从原来的中断号13,改为15.这是因为IAR和STVD对中断号的定义方法不一样,简单地理解就是:把资料中提供的中断号+2,就是IAR中的中断号。
改动3:用关键字__interrupt 作为函数void Timer2 (void)的前缀,表示这是中断处理函数。此函数定义之后,他处无需再做声明,否则会报错。 注意:关键字__interrupt 前面是两个下划杠。
经过以上的处理,定时器Timer2的中断已经可以被响应了。