建立一个属于自己的AVR的RTOS

合集下载

AVR单片机C语言项目开发实践教程项目一 AVR单片机系统开发与设计工具

AVR单片机C语言项目开发实践教程项目一 AVR单片机系统开发与设计工具

图2-14 进入调试状态
二、程序编译及下载
1.工程文件的建立与编译
点击全速运行
图2-15 程序全速仿真
二、程序编译及下载
1.工程文件的建立与编译
单步运行查看 单口状态
程序指针
点击单步运行 执行每条语句
图2-16 单步执行后的IO状态
二、程序编译及下载
2.示例程序说明
程序使用芯片ATmega16,频率为8MHz。如使用其他 芯片,需修改模拟调试选项中的芯片型号,并修改程序中 的头文件包含。程序所完成的功能:PC0接一LED。以 2Hz的频率闪烁。
图2-20 程序下载界面
三、AVR单片机软件仿真
如果在没用硬件实训箱,也可以利用软件仿真的形式 进行学习。本书简单介绍Proteus软件。
在单片机学习过程中,同学们更应该实际动手设计、 制作、调试,才能从硬件上真正提高自己的水平。
Proteus软件使用方法参照课本演示步骤进行操作。
AVR单片机(C语 言)项目开发实践 教程项目一 AVR单 片机系统开发与设
计工具
目录
一、WinAVR+AVR Studio软件开发环境使用 二、程序编译及下载 三、AVR单片机软件仿真
一、WinAVR+AVR Studio软件开发环境使用
1.AVR单片机嵌入式系统的开发平台AVR Studio ATMEL公司为开发使用AVR单片机提供了一套免费的
1.工程文件的建立与单步执行语句 单步执行语句或函数 跳出当前函数 运行到光标处 自动单步运行 在当前位置添加断点 取消所有断点 快速查看变量
图2-13 运行工具栏
二、程序编译及下载
1.工程文件的建立与编译
3、MCU运行监视

AVR studio使用指南

AVR studio使用指南

互联网上下载AVR STUDIO 4首先,请放松,我们首先要做的只是下载AVR开发软件和相关的资料。

下载前确保这些软件有效,下载的时间取决于你连接互联网的速度。

下载以下文件到你的计算机中(如C:\Temp)∙AVR STUDIO4:这个文件是一个完整的开发工具,包括编辑、仿真功能,利用这个工具,我们可以编辑源代码,并在AVR器件上运行。

这个文件大概15MB。

∙代码实例:这是一个用于演示完整代码,大概1KB。

∙AT90S8515数据手册:这是AT90S8515芯片的完整资料。

AT90S8515芯片是一款非常容易上手的AVR芯片。

现在你不用担心AVR其他型号的产品,以后你会发现AVR系列产品有非常大的相似性,你掌握了一款芯片(比如说8515),学会其他芯片也非常容易。

这个文件大概4MB。

∙指令说明:如果你要详细的了解各种指令的话,这个文件非常有用。

这个文件大概2MB。

如果以上的文件你都下载了,下面的工作就是安装软件了。

安装AVR Studio 4AVR Studio现在也提供版本3,不过版本4将逐步替代版本3。

使用Windows NT/2000/XP的用户请注意,安装AVR Studio软件时,必须使用管理员(Administrator)权限登陆,这是Windows系统限定只有管理员才可以安装新器件。

安装过程:1.双击AVRSTUDIO.EXE文件。

这是一个自解压文件,双击后系统询问将文件解压到哪个目录底下,一般情况下是放在系统默认临时目录下,这个目录是隐藏在你的硬盘中的。

为了记忆方便,一般输入指定的目录,如C:\temp。

2.当所有文件解压缩完成以后,打开temp目录,双击SETUP.EXE文件。

好了,开始安装了,推荐适用默认的安装路径,当然,用户也可以设定自己的安装路径,但是在指南中,我们使用默认路径。

好了,开发工具安装好了,就这么简单。

现在你可以开始编写代码,在AVR器件上运行了。

注意,将芯片资料和指令说明放在旁边,这些资料以后经常用到。

AtmelStudio-60简易入门教程(精炼实用)

AtmelStudio-60简易入门教程(精炼实用)

、建议工程文件AtmeIStUdi6.0这个全新的环境使用起来极其不顺手,因为首先我对AtmeIStUdiO以前的版本也根本没有使用经验,就根据很陌生,其次,这个新版本软件还根本没有人用,根本没有任何的相关教程资料,唯一可以参考的只是官网的比较简单的视频教程,还是英文讲解,反正没怎么搞透。

不过还是硬着头皮用下去,因为软件是免费的,而且当后來我知道代码编辑环境其实就是微软VS环境的时候,我就更不犹豫了,大家应该都了解VS的代码编写环境是很智能的,尤其自动补全功能。

现在,我己经能很熟练的使用AtmelSUdio6.0软件了,随若使用我也更加喜欢玩AVR单片机做一些小作品了,而不再用普通51和SrC了。

当使用熟练以后也就感觉到其实这个免费智能的编译环境其实是很简单的,那现在我就帮助更多喜欢使用AVR而没用使用AtmeIStUCliO软件的同学们轻松越过这一个门槛,进入一个美好的编程世界。

该软件的不足之处:一是软件相对较大,打开比较慢,但是运行还是比较顺利的;二是不支持山寨仿真器,这可苦了没钱的劳苦电工们了。

(不过我都是用ISP烧求调试,一般不用仿真)最下而附件有一个简单的LED_test工程文件,编译通过的。

大家可以试用。

下面开始介绍的软件工程的建立。

1. 软件总界面总体界面还是比较简洁的,和其他编译软件都是差不多的,而Jl•和KEIL软件的界面是很相似的,使用很方便。

•SiΛPage・.:m∙Ytvdkl‰dπvΛ⅞r∙Mo<ι曰T W rWV,Mι⅛t×ΛΛfPrqeCtOaQTOd‰WirHRPJj∙4)JfiJr¾ɔ⅛∙'∙';TJ Clo$«NKafterProxet⅛>ad J S*>OWp»®ecoy∣owCUtPHt⅛oαr2. 新建工程新建工程很简单:FlLE->NEW->Project然后就看到下而的新建工程界而了,选择第一个GCCCEXeCUtabIeTS就可以,第二个GcCCStatiCLibrary是用來新建.h文件的。

AVR教程(4):AVRStudio仿真调试快速入门

AVR教程(4):AVRStudio仿真调试快速入门

AVR教程(4):AVRStudio仿真调试快速入门发布: 2010-1-10 12:30 | 作者: tiankai | 来源: 电子园AVR单片机学习专区AVRStudio仿真调试快速入门[p=30, 2, left] ● AVRStudio的安装到 ATMEL 官方: .atmel./dyn/products/tools_card.asp?tool_id=2725 下载安装。

● AVRStudio之建立、打开相关调试文件--使用汇编语言,软件仿真若使用汇编语言进行源代码的编写,由于AVRSTUDIO自带ASM编译器,可以直接建立、打开。

[/p][p=30, 2,left][/p][p=30, 2,left][/p] 接着,进行代码编写,之后按进行编译。

--使用ICCAVR,软件仿真若使用C进行编写,由于AVRSTUDIO不带C编译器,所以需要打开相应的调试文件。

打开*.COF(使用ICCAVR编译器编写源代码)或*.D90文件(使用IAR 编译器编写源代码)。

这类文件与您需要调试的*.C文件所处同一文件夹。

下面以ICCAVR为例,进行介绍。

接着,保存*.aps文件,改文件将记录目标芯片、文件路径等信息。

在打开项目文件的时候,如下图:选择“AVR Simulator”,右边选择实际使用的器件型号,之后点击“Finish”即可进行软件仿真。

选择完成后,即可进行仿真调试了。

[p=30, 2, left] --使用JTAGICE仿真器,硬件仿真与软件仿真不同的是:在打开项目文件的时候,如下图:选择“JTAG ICE”,其它的步骤与软件仿真一致,见上。

[/p]--使用JTAG ICE mkII仿真器,硬件仿真与软件仿真不同的是:在打开项目文件的时候,如下图:选择“JTAG ICE”,其它的步骤与软件仿真一致,见上。

● AVRStudio之调试程序下面简单介绍使用AVRStudio进行仿真调试调试控制栏调试控制栏可以控制程序的执行状态,所有的调试控制都可以由菜单,快捷键和调试工具栏实现。

Linux下的AVR开发环境的建立

Linux下的AVR开发环境的建立
*** This configuration is not supported in the following subdirectories: target-libiberty (Any other directories should still work fine.) …… …… 我找了很多资料都没有解决,后来我有试了几个 GCC 的版本直到我用 gcc-core-3.0.3 的时候没有错误,make 也没有问 题安装也是成功的。 但是不知道为什么用 gcc-core-3.3 以上的版本就会出错,但是我也在网上看到别人用 3.3 以上版本编译成功的例子。后来 在 DSNC 那里才找到了答案“gcc 的有些版本是不太好用的,比较好用的版好像有 2.95, 3.4.6, 4.2.1/4.2.2”然后我就采用 了 4.2.2 版本 [root@localhostAtmel]#configure --target=avr --prefix=/home/c/r/mymtom/local --disable-nls --enable-language=c 这样还会报无法编译 libssp 的错误,按照 DSNC 那里大侠的指点加上了--disalbe-libssp 问题解决了。 下面是我的成功的步骤:
*** building gcc. Please change the environment variable *** and run configure again. 用 echo $LIBRARY_PATH 看发现我的 LIBRARY_PATH 变成了 jepg 库的路径(前几天 刚装的)不知道为什么会形象他。然后我把在/etc/profile 里去掉 jpeg 库的查找路径,系 统重启。问题少了很多,但是还是有一个错误:
在 linux shell 里运行一下命令: [root@localhost Atmel]# tar zxvf gcc-core-4.2.2.tar.gz [root@localhost Atmel]# cd gcc-core-3.3.6 [root@localhost Atmel]# ./configure --target=avr --prefix=/usr/local/atmel --disable-nls --enable-language=c --disable-libssp [root@localhost Atmel]# make [root@localhost Atmel]# make install

建立一个属于自己的AVR的RTOS

建立一个属于自己的AVR的RTOS

建立一个属于自己的AVR的RTOS (mega128)2009-09-26 16:46对原作者黄健昌先生表示由衷的感谢,正是这篇文章给我学习嵌入式操作系统铺平了道路,循序渐进、受益良多,由于正在使用mega128做项目,编译器为WinAVR20080610,所以将原文中的实例做了改动,并在开发板上进行了验证。

出于对原作者的尊敬,只对原文做一些必要的改动,基本上维持原貌。

第一篇:函数的运行在一般的单片机系统中,是以前后台的方式(大循环+中断)来处理数据和作出反应的。

例子如下:makefile的设定:运行WinAvr中的Mfile,设定如下MCU Type: mega128Optimization level: sDebug format :AVR-COFFC/C++ source file: 选译要编译的C文件#include <avr/io.h>#include <avr/Interrupt.h>#include <util/delay.h>void fun1(void){unsigned char i=0;while(1){i++;PORTC=0x01<<(i%8);_delay_ms(200);}}int main(void){DDRC=0xFF;fun1();}首先,提出一个问题:如果要调用一个函数,真是只能以上面的方式进行吗?相信学习过C语言的各位会回答,No!我们还有一种方式,就是“用函数指针变量调用函数”,如果大家都和我一样,当初的教科书是谭浩强先生的《C程序设计》的话,请找回书的第9.5节。

例子:用函数指针变量调用函数#include <avr/io.h>#include <avr/Interrupt.h>#include <util/delay.h>void fun1(void){unsigned char i=0;while(1){i++;PORTC=0x01<<(i%8);_delay_ms(200);}}void (*pfun)(); //指向函数的指针int main(void){DDRC=0xFF;pfun=fun1; //(*pfun)(); //运行指针所指向的函数}第二种,是“把指向函数的指针变量作函数参数”#include <avr/io.h>#include <avr/Interrupt.h>#include <util/delay.h>void fun1(void){unsigned char i=0;while(1){i++;PORTC=0x01<<(i%8);_delay_ms(200);}}void RunFun(void (*pfun)()) //获得了要传递的函数的地址{(*pfun)(); //在RunFun中,运行指针所指向的函数}int main(void){DDRC=0xFF;RunFun(fun1); //将函数的指针作为变量传递}看到上面的两种方式,很多人可能会说,“这的确不错”,但是这样与我们想要的RTOS,有什么关系呢?各位请细心向下看。

从零开始全面打造avr开发平台(avrgccide)

从零开始全面打造avr开发平台(avrgccide)

从零开始全面打造avr开发平台(avrgccide)本文讨论如何大造一个适合自己的软硬件开发环境,主要介绍avrgcc的windows下的集成开发环境avrgccide的使用及一些必备的硬件工具。

1,软件环境当前,常用的avr的编译器有atmel的avrstudio,iaravr,iccavr,codevisionavr,avrgcc,还有基于bas的几种软件。

调试器有avrstudio,iaravr,avrgcc,其他两种软件没有自己的调试器。

Iaravr,iccavr,codevisionavr都是商用软件,使用要支付大量的费用。

尤其是iaravr费用很高不是普通爱好者能够接受的。

(盗版例外)avrgcc是gnu组织开发的免费软件,功能强大,免费的资源较多,是我们学习的好选择。

但是使用较为复杂,入门很难。

有没有办法让使用avrgcc变得容易,avrgccide就是在这种环境下开发出来的,它可以让使用avrgcc像其他如iccavr一样简单,并且它集成在线下载器,可以让你的思想马上转变为现实,集成超级终端让您调试串口更为容易。

调试可通过它产生的.cof与avrstudio无缝结合或生成elf文件用avr-gdb调试(太繁琐不建议)。

目前它是免费的。

(关于avrgccide可以与mcu598@讨论) 2,安装avrgccide下载avrgccide包解压,双击setup安装,下一步,下一步直到安装完毕,下载最新的avrgccide解压覆盖同名文件,安装完成。

3,创建项目启动avrgccide,选择new project,选择工程目录输入工程名保存,添加文件(这里介绍的是usbasp的编译,以后还要使用这个usb的下载线呢—mega8的软件实现usb)。

下载usbasp包,将fireware目录下的文件解压倒您的工程目录。

将鼠标移到avrgccide的工程栏右击鼠标,将所有的.c,.s文件添加到工程。

简单方便自制的几个AVR-51 isp编程器(下载线)

简单方便自制的几个AVR-51 isp编程器(下载线)

简单方便自制的几个AVR/51 ISP编程器(下载线)AVR单片机有许多优点,我也是个忠实支持者,是从51过度到AVR的,中途还学PIC,初学51时买了学习板,液晶屏等不少东西,有经验后,学AVR时就从自制的下载线开始了,注意,这只是个开始,简单的东西总存在着一些局限性,但对于初学者来说,这可是个非常有用的东西,有了它就可以开始学习AVR单片机,甚至是一些开发了,这些编程器都是出自网上流传的,虽然我也不是很清楚出自那位高人,但感谢原作者.以下分享我的自制经验.1.由于AVR的编程方式有并行高压和串行ISP (In System Program 在系统编程)方式,高压并行编程能修复一些错误的配置位,但这并不常用,因为并行通信其布线会较多,不便于在成品中预留编程接口,也不便自制,而串行的ISP是基于SPI(Serial Peripheral interface)通信方式的,SPI通信时只需三根数据线, 分别是SCK,MISO,MOSI,再加上VCC,GND,Reset共需6根线,而VCC是可选的,用于向目标芯片供电,或由目标板反供电给编程器.那么设计目标板时,最少只要保留6根线,以后就可随时烧写,升级芯片上的程序了.而无需将芯片取下.这是ISP方式的最大特点,具体6根线连到那个引脚,不同型号不一样,要看芯片引脚定义图,例如ATtiny2313引脚定义如下:至于编程接头,尽可能以官方的10针接口为准,也可像我一样自定义一个6针的,因为我更喜欢水晶头,其实都是排列不同而已,只要再制作一条线进行转换就什么都搞定了.2.基于并口的ISP下载线,我最初也是自制了这款,这种下载线可以下载AVR全系列和AT89S系列51单片机,成本较低,不过需要PC机有并行口,许多笔记本电脑现在都没有并口了,比较麻烦,市场上卖的USB转并口,大都是用于打印机的,无法使用.以上是原理图,74HC244是用于信号的隔离驱动的,它从目标板经4148供电,由于ISP编程器只有4根是信号线,实际上我用了74HC125取代74HC244,以减小体积和引脚焊点数.下面是我使用的原理图,和成品图片:元件全装在内部,整体就很美观了,注意下载线不宜过长,最好50cm以内,PC上位机软件很多都可以支持的像双龙的SLISP,PonyProg2000(但51的型号很少,2.0a 版中也只有两个),智峰的progisp试过都成功烧写和效验.不足是烧写速度偏慢,综合来说还算满意.如果首次不成功,可能是软件设置问题,双龙的几乎不用(或说是不能)作什么设置,PonyProg200和Progisp或许需要设置一下才能把它使用得更好,比如Ponyprog用直接IO方式要比API方式快些,而Progisp它的端口引脚是可以自定义的,如果不同,把它设为和原理图一样不可以了.否则根本就用不了.3.基于串口的ISP下载线.,因为之前还在用51做些板子,初看这电路时,觉得由于reset在默认上拉,认为不适合51系列(51是高电平复位),并且更重要的是ponyprog2000的器件列表也没 89s52这型号,所以一直没去做过.但如果只对AVR编程来说,这个也是非常好用的.其中6,7端口必须直连,Ponyprog程序用来检测是否插入此接口,制作完成后试过还可以,速度和并口的差不多,只是必须要用PC机上的物理串口,用USB转串口的就无法使用.我起初觉得可能是驱动能力问题,曾用74HC125对它隔离驱动,花了时间却不成功,用示波器观察四条线的时序,发现原来是USB转串口线有问题,它的SCK(7脚),输出像随机的方波,而从物理串口出来的SCK时序,其频率在20K 左右,并连续稳定,如下图,这也许是USB转串口芯片的问题,才20K频率,难道被当燥声给滤掉了??请有了解的朋友请帮我分析一下,但这条转换线是好的,目前正在用它为ARM系统进行通迅,下载都很正常,芯片型号没打开看,驱动名称是Prolific USB-to-Serial Comm Port.有WHQL的,应该没问题,下面是我的原理图(我参考并口那个画的),实物,与波形.示波器测量时是直接测量转接口,未接下载线,通道1(绿)是物理串口的,通道2(黄)就是USB转串口的,已用示波器量了9个脚,不会错的,由于目前在学ARM9系统,已对这些问题放低了,对它有研究的朋友请告诉小弟,解决这小点问题,可以把它当USB的编程器用了!此线直接插到物理串口上,仍然可用.4.当制作完成这样简单的编程器后,就可以开始学习AVR或8051单片机了,熟悉后可以制作一个USB接口的编程器,USBASP,它内部是用一块ATMega8单片机来模似USB时序的,所以制作它的前提是至少需要一个编程器,例如上面的,将程序写入单片机中.这最好是在熟悉AVR的情况下制作.我是根据网上的公板图自己重画了这张原理图,来方便自己制作.晶振必须为12MHz,否则不可能完成USB时序的模似,单片机可以用低压版的ATMega8L 8PU超频使用,USB的数据线上的电压是3.3V,最高不超过3.6伏,那两个稳压管也就必须是3.6伏的,至于其它元件,其取值有些偏差影响也不大,JP1跳线是强制低速工作的,比如烧写那些有内部有RC振荡的单片机,首次使用就可能要用低速模式,因为其默认就是使用1M的内部振荡.由于USB供电已足够使用,JP5通常保持断开就可以了,JP3只在烧写或更新此编程器固件时使用,平时必须断开,整个电路其实很少东西,JP2连接USB线,或USB公头时要注意顺序不要搞错,上面这个PCB是专为万用板,有人叫洞洞板画的,并且4个LED位置是焊插针的,用来引出到外壳,这个单片机是直插的,建议不要焊上去,而是使用IC插座,当把电路做完,用表量一下确认无误后,插入USB口,此时PC端应该提示为无法识别的USB设备,不必理会,接着开始烧写固件,先短接JP3,再用另一个编程器通过编程口将程序写入Mega8单片机.此过程和平时烧写目标板是一样的.确认成功烧写和效验后,接着烧写熔丝位,这步主要就是设置单片机为外部晶振工作模式,设置熔丝时要小心,如果点错的话,先点恢复默认,再去修改.否则后果难以意料.下面分别是Ponyprog,progisp和SLISP的熔丝设置界面:注意不要设错,完成后将JP3取下,拔下并重插USB,如无意外,你会看到发现新硬件这样的提示,然后装USB驱动,就算大功告成了.至于软件目前就智峰的Progisp支持得比较好.因为经常用,最好是搞外壳保护它,我是在壳体店买的小盒,总之都是小问题了.那个低速开关我是用另一个8脚的单片机.实现按键检测,电平求反输出,和将状态保存到片内EEPROM进行记忆来实现的自锁开关,因为这是我后来扩展的,并且是用了PIC的12F629单片机,这些用AVR单片机(如Tiny13)实现都很简单,就不多说了,不过想它反应得好些要下些功夫,或者是直接用机械的自锁开关来实现.至此,可以慢慢享受自己的成果所带来的乐趣了.USBASP制作资料已打包,有兴趣的朋友可下载学习研究:(用浏览器打开,单线程下载)/self.aspx/.Public/MCU/u sbasp.rar。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
4
unsigned char add(unsigned char b,unsigned char c,unsigned char d) {
return b+c*d; } int main(void) {
unsigned char a=0; while(1) {
a++; PORTB=add(a,a,a); } } 在本例中,"add(a,a,a);"被编译如下: mov r20,r28 mov r22,r28 mov r24,r28 rcall add 第二个例子:定义通用寄存器为变量 #include <avr/io.h> unsigned char add(unsigned char b,unsigned char c,unsigned char d) { return b+c*d; } register unsigned char a asm("r20"); //将 r20 定义为 变量 a int main(void) { while(1) { a++; PORTB=add(a,a,a); } } 在本例中,"add(a,a,a);"被编译如下: mov r22,r20 mov r24,r20 rcall add 当然,在上面两个例子中,有部份代码被编译器优化了。 通过反复测试,发现编译器一般使用如下寄存器: 第 1 类寄存器,第 2 类寄存器的 r28,r29,第 3 类寄存器 如在中断函数中有调用基它函数,刚会在进入中断后,固定地将第 1 类寄存器和第 3 类寄存器入栈, 在退出中断又将它们出栈。
例:
#include <avr/io.h>
void fun1(void)
{
unsigned char i=0;
while(1)
{
PORTB=i++;
PORTC=0x01<<(i%8);
}
} unsigned char Stack[100]; //建立一个 100 字节的人工堆栈
void RunFunInNewStack(void (*pfun)(),unsigned char *pStack)
unsigned char i=0; while(1) { PORTB=i++; PORTC=0x01<<(i%8); } } int main(void) {
1
fun1();
} 首先,提出一个问题:如果要调用一个函数,真是只能以上面的方式进行吗? 相信学习过 C 语言的各位会回答,No!我们还有一种方式,就是“用函数指针变量调用函数”,如果大家 都和我一样,当初的教科书是谭浩强先生的《C 程序设计》的话,请找回书的第 10.5 节。 例子:用函数指针变量调用函数
2
对 main()中的 RunFun(fun1); 的编译如下 ldi r24,lo8(pm(fun1)) ldi r25,hi8(pm(fun1)) rcall RunFun 对 void RunFun(void (*pfun)())的编译如下 /*void RunFun(void (*pfun)())*/ /*(*pfun)();*/ .LM6: movw r30,r24 icall ret 在调用 void RunFun(void (*pfun)())的时候,的确可以把 fun1 的地址通过 r24 和 r25 传递给 RunFun()。 但是,RTOS 如何才能有效地利用函数的地址呢?
{
*pStack--=(unsigned int)pfun; /ned int)pfun>>8; //将函数的地址高位压入堆栈,
SP=pStack;
//将堆栈指针指向人工堆栈的栈顶
__asm__ __volatile__("RET \t"); //返回并开中断,开始运行 fun1()
} 第二种,是“把指向函数的指针变量作函数参数”
#include <avr/io.h>
void fun1(void)
{
unsigned char i=0;
while(1)
{
PORTB=i++;
PORTC=0x01<<(i%8);
}
} void RunFun(void (*pfun)()) //获得了要传递的函数的地址
#include <avr/io.h>
void fun1(void)
{
unsigned char i=0;
while(1)
{
PORTB=i++;
PORTC=0x01<<(i%8);
}
} void (*pfun)(); //指向函数的指针
int main(void)
{
pfun=fun1; // (*pfun)(); //运行指针所指向的函数
}
3
int main(void) {
RunFunInNewStack(fun1,&Stack[99]); } RunFunInNewStack(),将指向函数的指针的值保存到一个 unsigned char 的数组 Stack 中,作为人工堆栈。 并且将栈顶的数值传递组堆栈指针 SP,因此当用"ret"返回时,从 SP 中恢复到 PC 中的值,就变为了指向 fun1() 的地址,开始运行 fun1(). 上面例子中在 RunFunInNewStack()的最后一句嵌入了汇编代码 "ret",实际上是可以去除的。因为在 RunFunInNewStack()返回时,编译器已经会加上"ret"。我特意写出来,是为了让大家看到用"ret"作为返回后 运行 fun1()的过程。
建立一个属于自己的 AVR 的 RTOS

自从 03 年以来,对单片机的 RTOS 的学习和应用的热潮可谓一浪高过一浪.03 年,在离开校园前的, 非典的那几个月,在华师的后门那里买了本邵贝贝的《UCOSII》,通读了几次,没有实验器材,也不了了 之。
在 21IC 上,大家都可以看到杨屹写的关于 UCOSII 在 51 上的移植,于是掀起了 51 上的 RTOS 的热潮。 再后来,陈明计先生推出的 small rots,展示了一个用在 51 上的微内核,足以在 52 上进行任务调度。 前段时间,在 ouravr 上面开有专门关于 AVR 的 Rtos 的专栏,并且不少的兄弟把自己的作品拿出来, 着实开了不少眼界。这时,我重新回顾了使用单片机的经历,觉得很有必要,从根本上对单片机的 RTOS 的知识进行整理,于是,我开始了编写一个用在 AVR 单片机的 RTOS。 当时,我所有的知识和资源有: 1、Proteus6.7 可以用来模拟仿真 avr 系列的单片机 2、WinAVR v2.0.5.48 基于 GCC AVR 的编译环境,好处在于可以在 C 语言中插入 asm 的语句 3、mega8 1K 的 ram 有 8K 的 rom,是开发 8 位的 RTOS 的一个理想的器件,并且我对它也比较熟悉。 写 UCOS 的 Jean brosse 在他的书上有这样一句话,“渐渐地,我自然会想到,写个实时内核直有那 么难吗?不就是不断地保存,恢复 CPU 的那些寄存器嘛。” 好了,当这一切准备好后,我们就可以开始我们的 Rtos for mega8 的实验之旅了。 本文列出的例子,全部完整可用。只需要一个文件就可以编译了。我相信,只要适当可用,最简单的 就是最好的,这样可以排除一些不必要的干扰,让大家专注到每一个过程的学习。
第二篇: 人工堆栈
在单片机的指令集中,一类指令是专门与堆栈和 PC 指针打道的,它们是 rcall 相对调用子程序指令 icall 间接调用子程序指令 ret 子程序返回指令 reti 中断返回指令 对于 ret 和 reti,它们都可以将堆栈栈顶的两个字节被弹出来送入程序计数器 PC 中,一般用来从子程 序或中断中退出。其中 reti 还可以在退出中断时,重开全局中断使能。 有了这个基础,就可以建立我们的人工堆栈了。
第一篇:函数的运行
在一般的单片机系统中,是以前后台的方式(大循环+中断)来处理数据和作出反应的。 例子如下: makefile 的设定:运行 WinAvr 中的 Mfile,设定如下 MCU Type: mega8 Optimization level: s Debug format :AVR-COFF C/C++ source file: 选译要编译的 C 文件 #include <avr/io.h> void fun1(void) {
经理先进入;如果是占先式,只要有更高级的人在外面等,那么厕所里无论是谁,都要第一时间让出来,
让最高级别的人先用。”
#include <avr/io.h>
#include <avr/Interrupt.h>
第三篇:GCC 中对寄存器的分配与使用
在很多用于 AVR 的 RTOS 中,都会有任务调度时,插入以下的语句: 入栈: __asm__ __volatile__("PUSH R0 \t"); __asm__ __volatile__("PUSH R1 \t"); ...... __asm__ __volatile__("PUSH R31 \t"); 出栈 __asm__ __volatile__("POP R31 \t"); ...... __asm__ __volatile__("POP R1 \t"); __asm__ __volatile__("POP R0 \t"); 通常大家都会认为,在任务调度开始时,当然要将所有的通用寄存器都保存,并且还应该保存程序状 态寄存器 SREG。然后再根据相反的次序,将新任务的寄存器的内容恢复。 但是,事实真的是这样吗?如果大家看过陈明计先生写的 small rots51,就会发现,它所保存的通用寄存 器不过是 4 组通用寄存器中的 1 组。 在 Win AVR 中的帮助文件 avr-libc Manual 中的 Related Pages 中的 Frequently Asked Questions,其实有一 个问题是"What registers are used by the C compiler?" 回答了编译器所需要占用的寄存器。一般情况下,编译 器会先用到以下寄存器 1 Call-used registers (r18-r27, r30-r31): 调用函数时作为参数传递,也就是用得最多的寄存器。 2 Call-saved registers (r2-r17, r28-r29): 调用函数时作为结果传递,当中的 r28 和 r29 可能会被作为指向堆 栈上的变量的指针。 3 Fixed registers (r0, r1): 固定作用。r0 用于存放临时数据,r1 用于存放 0。 还有另一个问题是"How to permanently bind a variable to a register?",是将变量绑定到通用寄存器的方 法。而且我发现,如果将某个寄存器定义为变量,编译器就会不将该寄存器分配作其它用途。这对 RTOS 是很重要的。 在"Inline Asm"中的"C Names Used in Assembler Code"明确表示,如果将太多的通用寄存器定义为变量, 刚在编译的过程中,被定义的变量依然可能被编译器占用。 大家可以比较以下两个例子,看看编译器产生的代码:(在*.lst 文件中) 第一个例子:没有定义通用寄存器为变量 #include <avr/io.h>
相关文档
最新文档