打印

IAR for STM8 学习日记

[复制链接]
5393|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
KEVIN1973|  楼主 | 2014-12-6 16:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 KEVIN1973 于 2014-12-6 22:29 编辑

之前用过一段时间的STVD+COSMIC做项目,使用的芯片是STM8S105,后来因为项目的需要,改用STM8S207,结果COSMIC和STVD的安装目录里居然会找不到需要的头文件。后来在网上看到有些人是用IAR作为开发环境,于是便尝试着转向使用IAR做开发,因为网上关于IAR FOR STM8的帖子十分少见,于是我有了用此贴记录下我在学习过程中遇到的问题的想法,既是抛砖引玉,也是希望为后来者做一个指引,便于新手快速掌握,聊以此文作为本帖的开篇吧。

相关帖子

沙发
KEVIN1973|  楼主 | 2014-12-6 16:55 | 只看该作者
本帖最后由 KEVIN1973 于 2014-12-8 20:04 编辑

问题一:IAR中如何做位定义,位操作。
以前在STVD中,使用如下语句做位定义
_Bool L1            @PA_ODR : 6;        //数码管个位, 低电平点亮
_Bool L2            @PA_ODR : 5;        //数码管十位, 低电平点亮
_Bool L3            @PA_ODR : 4;        //数码管百位, 低电平点亮
但是同样的语句在IAR中不能用了,编译时报错。
后来,查看IAR中的头文件 "iostm8s207rb.h",看到如下语句
/*-------------------------------------------------------------------------
*      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语句结尾是不需要用分号的!

使用特权

评论回复
板凳
KEVIN1973|  楼主 | 2014-12-6 22:38 | 只看该作者
问题二:IAR中是否支持二进制数的使用
以前在STVD+COSMIC的环境下,端口初始化的语句为:
PA_DDR = 0B10000000;
在IAR环境中,本语句报错,于是网上到处查找,结果大多数的说法是:IAR可以支持8、10、16进制,但是不支持2进制的表达方式。哎,没办法,之后改为如下方式:
PA_DDR = 0X80;  //0B 1000 0000
将原二进制数据作为注释。经过测试,编译可以通过。

使用特权

评论回复
地板
KEVIN1973|  楼主 | 2014-12-9 09:10 | 只看该作者
本帖最后由 KEVIN1973 于 2014-12-9 09:13 编辑

问题三:中断处理
在本项目中需要用到多个中断,其中就包括定时器中断。之前在STVD环境下开发时,只要新建一个工程,系统就会自动为你添加main.c和stm8_interrupt_vector.c这两个函数,而且stm8_interrupt_vector.c函数中,已写好了很多代码,实际使用时,只需要写下自己的中断处理函数,然后将函数名复制到中断号相对应的结构体中即可被调用,部分代码如下:
@far @interrupt void Timer2 (void)
{   
   
//------  清除中断标志
    TIM2_SR1=TIM2_SR1 & 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的中断已经可以被响应了。

使用特权

评论回复
5
仙人球W| | 2015-3-18 08:41 | 只看该作者
漂亮!我还在为找IAR软件下载地址中! 最近,为了节省成本几款STM32的芯片要换成STM8的 就不能用KEIL开发了

使用特权

评论回复
6
Tuerxun| | 2015-11-19 14:58 | 只看该作者
mark

使用特权

评论回复
7
stone1985d| | 2016-5-3 10:24 | 只看该作者
MARK

使用特权

评论回复
8
banana323| | 2016-5-31 17:32 | 只看该作者
MARK

使用特权

评论回复
9
漫步i星空| | 2017-9-12 10:59 | 只看该作者
太赞了!!!!!!!

使用特权

评论回复
10
viphq1314| | 2017-9-22 12:13 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

17

帖子

0

粉丝