智能车制作

 找回密码
 注册

扫一扫,访问微社区

查看: 17516|回复: 46
打印 上一主题 下一主题

龙丘智能科技贡献:MC9S12DG128 EEPROM完美版读写程序

  [复制链接]

80

主题

1045

帖子

0

精华

跨届大侠

北京龙邱智能科技有限公司

Rank: 10Rank: 10Rank: 10

积分
10332

论坛元老奖章

QQ
威望
2905
贡献
6151
兑换币
4515
注册时间
2008-6-7
在线时间
638 小时
跳转到指定楼层
1#
发表于 2009-11-20 20:35:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
下面是一个完整的MC9S12DG128 EEPROM读写程序,程序来源于网络,反馈于网络,对大家肯定有用!下面仅贴出部分主文件和主函数,完整工程可以下载附件,开发板用户可以直接操作演示程序。
/********************************************************
龙丘MC9S12DG128 多功能开发板
Designed by Chiu Sir
E-mail:chiusir@163.com
软件版本:V1.2
最后更新:2009年8月25日
相关信息参考下列地址:
网站:  http://www.lqist.cn
论坛:  http://smartcar.5d6d.com
淘宝店:http://shop36265907.taobao.com
------------------------------------
Code Warrior 5.0
Target : MC9S12dg128b
Crystal: 16.000Mhz
busclock:16.000MHz
pllclock:32.000MHz
------------------------------------
【程序使用说明】:
【重要修改】
在Start12.c文件最前面加入:#define _HCS12_SERIALMON
在Project.prm中:
    添加下面的代码:
      EEPROM        = READ_ONLY     0x0800 TO   0x0FFB;
    修改下面的代码:
      RAM           = READ_WRITE    0x2000 TO   0x3FFF;
     
【串口波特率】:9600,n,8,1
【按UP】    修改欲写入的数据
【按OK】    对块的读操作
【按ESC】   对块的重新写入数据
【使用步骤】:
1.插上电源和串口线,并打开串口调试工具
2.按ESC读取原始数据
3.按UP/DOWN修改欲写入的数据
4.按OK写入新数据
5.复位单片机然后按ESC读取上次写入的数据,比对保存结果.  
*****************************************************************************************/
#i nclude <hidef.h>   
#i nclude "derivative.h"
#i nclude "LQprintp.h"
#i nclude "LQEEPROM.h"
volatile word testnumber=0;
/**************************************************
复杂测试操作:
1.按ESC读取原始数据
2.按UP/DOWN修改欲写入的数据
3.按OK写入新数据
4.复位单片机然后按ESC读取上次写入的数据,比对保存结果.
***************************************************/
void Test_EE_WriteRead(void)
{
    word cnt;
   
    if(PTIH_PTIH7==0)       //OK
    {
       printp("write and read data:\n");
       for(cnt=0;cnt<10;cnt+=2)         
       {         
          EEP_Wt_Word(EEPROM_ADDR_BASE+cnt,0xffff,EEP_Word_Erase);   
          EEP_Wt_Word(EEPROM_ADDR_BASE+cnt  ,0x1200+cnt+testnumber  ,EEP_Word_Prog);
          EEP_Wt_Word(EEPROM_ADDR_BASE+cnt+1,0x1200+cnt+testnumber+1,EEP_Word_Prog);
          u16ata=EEP_Rd_Word(EEPROM_ADDR_BASE+cnt);
          printp("%04x,",u16ata);
          u16ata=EEP_Rd_Word(EEPROM_ADDR_BASE+cnt+1);
          printp("%04x,",u16ata);         
       }
       printp("\n");
    }
    else if(PTIH_PTIH6==0)  //ESC
    {
       printp("read data:\n");
       for(cnt=0;cnt<10;cnt+=2)         
       {
         u16ata=EEP_Rd_Word(EEPROM_ADDR_BASE+cnt);
         printp("%04x,",u16ata);
         u16ata=EEP_Rd_Word(EEPROM_ADDR_BASE+cnt+1);
         printp("%04x,",u16ata);         
       }
       printp("\n");
    }
    else if(PTIH_PTIH2==0)  //UP
    {      
      printp("cnt:%04x \n",++testnumber);
    }
    else if(PTIH_PTIH5==0)  //DOWN
    {      
      printp("cnt:%04x \n",--testnumber);
    }
}
/**************************************************
总线时钟初始化函数:16MHz=晶振频率
编写:龙丘
最后修改:2009.11.18
***************************************************/
static void Set_Bus_16M(void)
{  
    CLKSEL=0X00;    //disengage PLL to system
    PLLCTL_PLLON=1;   //turn on PLL
    SYNR=1;         
    REFDV=1;          //pllclock=2*osc*(1+SYNR)/(1+REFDV)=32MHz;
    _asm(nop);          //BUS CLOCK=16M
    _asm(nop);
    while(!(CRGFLG_LOCK==1));   //when pll is steady ,then use it;
    CLKSEL_PLLSEL =1;          //engage PLL to system;
}
/**************************************************
main()
编写:龙丘
最后修改:2009.11.18
***************************************************/
void main(void)
{
  Set_Bus_16M();
  SCI_Init();
  printp("started!\n");
  DDRB =0xff;
  PORTB=0x00;
  EEPROM_init();   
  DisableInterrupts;
  PORTB=0xFF;
  for(;;)
  {
      //Simple_Test();
      Test_EE_WriteRead();
      Dly_ms(500);
      PORTB_BIT0=~ PORTB_BIT0;
  } /* wait forever */
  /* please make sure that you never leave this */
}

/**************************************************
延时函数:ms个毫秒
编写:龙丘
最后修改:2009.11.18
***************************************************/
void Dly_ms(int ms)  //x取值1~65536;
{
  int ii,jj;
   if (ms<1) ms=1;
   for(ii=0;ii<ms;ii++)
     for(jj=0;jj<1335;jj++);    //16MHz--1ms   
}
/**************************************************
延时函数:ms个毫秒
编写:龙丘
最后修改:2009.11.18
***************************************************/
void Dly_10us(int ms)  //x取值1~65536;
{
  int ii,jj;
   if (ms<1) ms=1;
   for(ii=0;ii<ms;ii++)
     for(jj=0;jj<13;jj++);    //16MHz--10us   
}
/*************************************************                 
EEPROM模块初始化程序  
编写:龙丘
最后修改:2009.11.18        
*************************************************/
void EEPROM_init(void)
{
    ECLKDIV=0x4A;                   // 采用8分频,因为OSCLK=16M,又为了使ECLK
                                    // 达到190KHZ,所以EDIV=21,即ECLK=16M/8/11=190.5KHZ
    ECNFG=0x00;                     // 禁止EEPROM相关操作的中断
    while(ECLKDIV_EDIVLD == 0);     // 等待时钟设置成功
    EPROT_EPOPEN=1;                 // EEPROM没有保护,可以进行编程与擦除
    EPROT_EPDIS=1;                  // EEPROM保护禁止
}
/*************************************************               
写EEPROM程序      
Addr:  要操作的EEPROM偏移地址
Data:  要操作的EEPROM数据
OpType:操作命令类型  
编写:龙丘                  
*************************************************/
void EEP_Wt_Word(word * Addr,word Data,byte OpType)
{
    DisableInterrupts;
    while(ESTAT_CBEIF == 0);        // 等待EEPROM命令缓冲区为空
    *Addr=Data;                     // 设置EEPROM的偏移地址
    ECMD=OpType;                    // 指令的类型
    ESTAT |= 0x80;                  // 清命令缓冲标志,开始执行命令
    while(ESTAT_CCIF == 0);         // 等待命令完成
    EnableInterrupts;
}
/*************************************************               
读EEPROM程序                 
Addr:  要操作的EEPROM偏移地址
返回值:读到的结果数据  
编写:龙丘
最后修改:2009.11.18               
*************************************************/
word EEP_Rd_Word(word * Addr)
{
    word TempData;
    DisableInterrupts;
    TempData=*Addr;                 // 读EEPROM的偏移地址的数据
    return(TempData);   
}
/*************************************************         
简单测试操作
编写:龙丘
最后修改:2009.11.18                  
*************************************************/
void Simple_Test(void)
{
   word cnt;   
   
   printp("write and read data:\n");
   for(cnt=0;cnt<1024;cnt+=2)         
   {         
      EEP_Wt_Word(EEPROM_ADDR_BASE+cnt,0xffff,EEP_Word_Erase);   
      EEP_Wt_Word(EEPROM_ADDR_BASE+cnt  ,0x1200+cnt,EEP_Word_Prog);
      EEP_Wt_Word(EEPROM_ADDR_BASE+cnt+1,0x1200+cnt+1,EEP_Word_Prog);
      u16ata=EEP_Rd_Word(EEPROM_ADDR_BASE+cnt);
      printp("%04x,",u16ata);
      u16ata=EEP_Rd_Word(EEPROM_ADDR_BASE+cnt+1);
      printp("%04x,",u16ata);      
      if(cnt%16==0) printp("\n");         
   } }
完整工程可以下载附件(密码:longqiu):

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

7

主题

262

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2478
威望
499
贡献
1803
兑换币
0
注册时间
2009-5-12
在线时间
88 小时
2#
发表于 2009-11-20 21:27:32 | 只看该作者
支持~~~~~多谢分享
回复 支持 反对

使用道具 举报

0

主题

135

帖子

0

精华

高级会员

Rank: 4

积分
767
威望
319
贡献
76
兑换币
6
注册时间
2009-6-22
在线时间
186 小时
3#
发表于 2009-11-20 23:53:00 | 只看该作者
DG128看来是不让用了,不如讲讲XS128的D-Flash?
回复 支持 反对

使用道具 举报

22

主题

518

帖子

0

精华

版主

Rank: 9Rank: 9Rank: 9

积分
6442
QQ
威望
943
贡献
5041
兑换币
99
注册时间
2008-2-26
在线时间
229 小时
4#
发表于 2009-11-21 12:02:37 | 只看该作者
学习了
回复 支持 反对

使用道具 举报

1

主题

21

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
266
威望
208
贡献
28
兑换币
4
注册时间
2009-11-1
在线时间
15 小时
5#
发表于 2010-3-6 01:26:36 | 只看该作者
回复 支持 反对

使用道具 举报

0

主题

72

帖子

0

精华

高级会员

Rank: 4

积分
593
QQ
威望
310
贡献
73
兑换币
16
注册时间
2008-12-6
在线时间
105 小时
6#
发表于 2010-4-1 16:42:03 | 只看该作者
太强大了,谢谢!
回复 支持 反对

使用道具 举报

0

主题

10

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
202
威望
180
贡献
20
兑换币
0
注册时间
2010-4-4
在线时间
1 小时
7#
发表于 2010-4-4 16:52:11 | 只看该作者
很好
回复 支持 反对

使用道具 举报

0

主题

86

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
339
威望
280
贡献
53
兑换币
12
注册时间
2010-3-29
在线时间
3 小时
8#
发表于 2010-4-13 12:43:38 | 只看该作者
多谢
回复 支持 反对

使用道具 举报

2

主题

104

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1571
威望
713
贡献
292
兑换币
90
注册时间
2009-3-14
在线时间
283 小时
9#
发表于 2010-4-13 20:42:59 | 只看该作者
[单片机] 关于PLL超频的个人心得
PLL, 超频, 心得
本帖最后由 chenrunshe_007 于 2010-3-18 00:23 编辑

废话少说,我们先来看两段代码: //Code1

void SetBusClock(void)

{

CLKSEL=0X00;           // disengage PLL to system

PLLCTL_PLLON=1;       // turn on PLL

SYNR=0x00 | 0x02;    // VCOFRQ[7:6];SYNDIV[5:0];fVCO= 2*fOSC*(SYNDIV + 1)/(REFDIV + 1);fPLL= fVCO/(2 × POSTDIV);fBUS= fPLL/2

REFDV=0x80 | 0x01;  // REFFRQ[7:6];REFDIV[5:0]

_asm(nop);               // BUS CLOCK=24MHz

_asm(nop);

while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it;

CLKSEL_PLLSEL =1;  //engage PLL to system;

}
复制代码这时候有人说:你这不是废话吗,地球人都知道这段代码,根据公式,可以算出F_Bus=24MHz,不是我无聊没事干写这玩意来开刷大家,大家请耐心点再看另一段代码: //Code2

void SetBusClock(void)

{

CLKSEL=0X00;         // disengage PLL to system

PLLCTL_PLLON=1;    // turn on PLL

SYNR=0x00 | 0x0B;     // VCOFRQ[7:6];SYNDIV[5:0];fVCO= 2*fOSC*(SYNDIV + 1)/(REFDIV + 1);fPLL= fVCO/(2 × POSTDIV);BUS= fPLL/2

REFDV=0x00 | 0x07;    // REFFRQ[7:6];REFDIV[5:0]

_asm(nop);             // BUS CLOCK=24M

_asm(nop);

while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it;

CLKSEL_PLLSEL =1;//engage PLL to system;

}
复制代码聪明的你看出这两段代码的区别了吧?对,第二段代码同样可以超频到24MHz,但是用了不同的方法,很久以前,我曾经在论坛上面看见过有人问过这个问题,说同样是超频到24MHz,16X(2+1)/(1+1)=24和16X(11+1)/(7+1)=24有什么区别?我当时还没太注意,经过试验发现真没什么区别,等到今年我调的时候就发现了,大家可以看得出如果用的是代码1,超频每次增加的基数是8MHz,而代码2可以小到2MHz,做LED和EM可能还没这个感受,做CCD的就会深刻的体验,超频每快2MHz对图像处理的好处。也就是说使用代码1,你想超频更多,就必须每次8MHz增加,而用代码2,每次你可以增加2MHz,慢慢增加直到不能再超为止,给大家说下我们的例子,我们用的是龙丘的112Pin的板子,用代码1的话只能超到88MHz,再往上怎么也超不到96MHz,而用代码2的话,可以开始试88、90、92、94、96……,最后最高发现可以在94MHz那里达到稳定,比原来预计的88MHz多了6MHz,如果大家用的是龙丘的80Pin的板子,那可能就能超得过96,或者更高了。这种细节大家不要小看它,很多有利的细节加在一起可能就能在成功之路上助你一臂之力。
不过本人倒是有个疑问,某权威说过,LED不用超频那么多,有24MHz够用了,我们用的是激光扫描探测方法,模拟CCD的处理,可能处理的信息会比较多,如果我能超到94MHz,那岂不是比24MHz快了整整将近4倍!在这种“诱惑”下,我们快把持不住了,所以也就超了,觉得好像也没有什么超的多就会不稳定的事情发生,童鞋们觉得怎么样。
1.追求运行速度还是追求稳定重要?
2.到底超频超得多是不是一定会导致运行不稳定?能帮本人解决这两个问题,不胜感激。

以上仅代表个人意见,欢迎指出不足的地方。
PS:代码是引用龙丘的例程修改,特此做一下说明
回复 支持 反对

使用道具 举报

1

主题

95

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
385
威望
301
贡献
16
兑换币
0
注册时间
2010-1-7
在线时间
34 小时
10#
发表于 2010-4-18 17:57:56 | 只看该作者
谢谢
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

关于我们|联系我们|小黑屋|智能车制作 ( 黑ICP备2022002344号

GMT+8, 2024-12-27 16:55 , Processed in 0.371842 second(s), 32 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表