[求助] 关于STC89C52和AT89S52的不同

小杜在此   2013-11-20 22:52 楼主
刚编写了一个收音机程序,烧录STC可以使用,但是烧录AT后没法正常工作,这是什么原因。下面是写的程序(分模块写的)
  1. /******************************************************************
  2. *                                                                *
  3. *  K1--- 向上搜索电台 K2--- 向下搜索电台                         *
  4. *  K3--- 音量加       K4--- 音量减                               *
  5. *                                                                *
  6. *****************************************************************/

  7. #include
  8. #include
  9. #include "lcd.h"
  10. #include "IIC.h"
  11. #include "delay.h"

  12. sbit  K1 = P2^1;
  13. sbit  K2 = P2^2;
  14. sbit  K3 = P2^3;
  15. sbit  K4 = P2^4;

  16. unsigned long frequency;

  17. // RDA5807 寄存器
  18. unsigned char  RDA_reg_data[8] =
  19. {
  20.    0xd0,0x00,  // 02H
  21.    0x00,0x00,  // 03H
  22.    0x00,0x40,  // 04H
  23.    0x90,0x88,  // 05H
  24. };

  25. unsigned char code  cdis1[ ] = {"FM STEREO RADIO "};
  26. unsigned char code  cdis2[ ] = {"FM       VOL    "};

  27. char code reserve[3]_at_ 0x3b; //保留0x3b开始的3个字节

  28. /**********************************************************

  29. 连续写寄存器子函数

  30. **********************************************************/
  31. void RDA5807_write_reg(void)
  32. {
  33.    uchar i;

  34.    I2C_start();
  35.     // 收音模块写入操作
  36.    I2C_write_byte(0x20);
  37.     // 寄存器连续写操作
  38.    for(i=0; i<8; i++)
  39.    {
  40.      I2C_write_byte(RDA_reg_data[i]);
  41.    }
  42.    I2C_stop();
  43. }

  44. /**********************************************************

  45. 连续读寄存器子函数

  46. **********************************************************/
  47. void RDA5807_read_reg(uchar *reg_buf)
  48. {
  49.    I2C_start();

  50.     // 收音模块读取操作
  51.    I2C_write_byte(0x21);

  52.     // 寄存器连续读操作
  53.    reg_buf[0] = I2C_read_byte(I2C_ACK);
  54.    reg_buf[1] = I2C_read_byte(I2C_ACK);
  55.    reg_buf[2] = I2C_read_byte(I2C_ACK);
  56.    reg_buf[3] = I2C_read_byte(I2C_NACK);

  57.    I2C_stop();
  58. }

  59. /**********************************************************

  60. 模块上电初始化子函数

  61. **********************************************************/
  62. void RDA5807_power(void)
  63. {
  64.    delayms(50);

  65.     // 发送软件复位指令
  66.    RDA_reg_data[0] = 0x00;
  67.    RDA_reg_data[1] = 0x02;
  68.    RDA5807_write_reg();

  69.    delayms(10);

  70.     // 收音模块默认参数
  71.    RDA_reg_data[0] = 0xd0;
  72.    RDA_reg_data[1] = 0x01;
  73.    RDA5807_write_reg();
  74. }
  75. /**********************************************************

  76. 功能描述:收音模块自动寻台模式

  77. **********************************************************/
  78. void RDA5807_FM_seek(void)
  79. {
  80.    uint chan;
  81.    uchar  reg_data[4] = {0x00, 0x00, 0x00, 0x00};

  82.    RDA_reg_data[3] &= ~(1 << 4);      //调谐禁用

  83.    // 内部自动寻台使能
  84.    RDA_reg_data[0] |=  (1 << 0);      //SEEK位置1
  85.    RDA5807_write_reg();

  86.     // 等待STC 标志置位
  87.    while(0 == (reg_data[0] & 0x40))
  88.    {
  89.      delayms(20);
  90.       // 读取内部状态
  91.      RDA5807_read_reg(reg_data);
  92.    }
  93.     // 获取当前工作频点
  94.    chan = reg_data[0] & 0x03;
  95.    chan = reg_data[1] | (chan << 8);
  96.    chan = chan << 6;

  97.     // 保存当前工作频点
  98.    RDA_reg_data[2] = (chan >> 8) & 0xff;
  99.    RDA_reg_data[3] = (chan & 0xff);
  100. }

  101. /**********************************************************

  102. 频率显示子函数

  103. **********************************************************/
  104. void  show_frequency(void)
  105. {
  106.    unsigned char i,display[5];
  107.    unsigned int  temp;

  108.    temp = (RDA_reg_data[2]*256)+(RDA_reg_data[3]&0xc0);         //计算
  109.    temp = temp>>6;
  110.    frequency = (unsigned long)(100*temp+87000)/100;

  111.    for(i=0; i<5; i++)  // 清显存单元
  112.    display[i] = 0x00;

  113.    display[0] = (frequency)/1000 ;     //数据转换
  114.    display[1] = (frequency%1000)/100;
  115.    display[2] = (frequency%100)/10;
  116.    display[3] = 0x2e;                  //小数点
  117.    display[4] = (frequency%10);

  118.    if(display[0] == 0)
  119.    {
  120.      display[0] = display[1]+0x30;
  121.      display[1] = display[2]+0x30;
  122.      display[2] = display[3];
  123.      display[3] = display[4]+0x30;
  124.      display[4] = 0x20;
  125.    }
  126.    else
  127.    {
  128.      display[0] += 0x30;
  129.      display[1] += 0x30;
  130.      display[2] += 0x30;
  131.      display[4] += 0x30;
  132.    }

  133.    lcd_pos_xy(3,2);                      //频率显示
  134.    lcd_wdat(display[0]);
  135.    lcd_wdat(display[1]);
  136.    lcd_wdat(display[2]);
  137.    lcd_wdat(display[3]);
  138.    lcd_wdat(display[4]);
  139. }

  140. /**********************************************************

  141. 音量显示子函数

  142. **********************************************************/
  143. void show_volume()
  144. {
  145.    unsigned char temp,display[2];

  146.    temp = RDA_reg_data[7] & 0x0f; //取音量值

  147.    display[0] = temp/10;
  148.    display[1] = temp%10;

  149.    if(display[0] == 0)            //如果高位为0
  150.    {
  151.      display[0] = display[1];     //低位显存内容进入高位显存
  152.      display[1] = 0x20;           //低位不显示
  153.    }
  154.    else
  155.    {
  156.      display[1] += 0x30;
  157.    }
  158.    display[0] += 0x30;

  159.    lcd_pos_xy(13,2);              //音量值显示
  160.    lcd_wdat(display[0]);
  161.    lcd_wdat(display[1]);
  162. }

  163. /**********************************************************

  164. 主函数

  165. **********************************************************/
  166. void  main(void)
  167. {  
  168.    P0 = 0xff;
  169.    P1 = 0xff;
  170.    P2 = 0xff;
  171.    lcd_init();
  172.    lcd_w_string(0,1,cdis1,0);
  173.    lcd_w_string(0,2,cdis2,0);

  174.    RDA5807_power();

  175.    while(1)
  176.    {
  177.      if(K1 == 0)
  178.      {
  179.        delayms(20);
  180.        if(K1 == 0)
  181.        {
  182.          RDA_reg_data[0] |= (1 << 1);         //SEEK UP         
  183.          RDA5807_FM_seek();                  
  184.          while(K1 == 0);
  185.        }
  186.      }

  187.      if(K2 == 0)
  188.      {
  189.        delayms(20);
  190.        if(K2 == 0)
  191.        {
  192.          RDA_reg_data[0] &= ~(1 << 1);  //SEEK DOWN                 
  193.          RDA5807_FM_seek();
  194.          while(K2 == 0);
  195.        }
  196.      }

  197.      if(K3 == 0)
  198.      {
  199.        delayms(20);
  200.        if(K3 == 0)
  201.        {
  202.          if((RDA_reg_data[7] & 0x0f) < 0x0f)
  203.          {
  204.            RDA_reg_data[0] = 0xd0;
  205.            RDA_reg_data[1] = 0x01;
  206.            RDA_reg_data[3] &= ~(1 << 4);

  207.            RDA_reg_data[7]++;         // 音量递增
  208.            RDA5807_write_reg();
  209.                    while(K3 == 0);
  210.          }
  211.        }
  212.      }

  213.      if(K4 == 0)
  214.      {
  215.        delayms(20);
  216.        if(K4 == 0)
  217.        {
  218.          if((RDA_reg_data[7] & 0x0f) > 0x00)
  219.          {
  220.            RDA_reg_data[0] = 0xd0;
  221.            RDA_reg_data[1] = 0x01;
  222.            RDA_reg_data[3] &= ~(1 << 4);
  223.            
  224.            RDA_reg_data[7]--;         // 音量递减
  225.            RDA5807_write_reg();
  226.            while(K4 == 0);
  227.          }
  228.        }
  229.      }

  230.      show_volume();
  231.      show_frequency();
  232.    }
  233. }

  234. /*********************************************************/



  235. #include
  236. #include "lcd.h"
  237. #include "delay.h"
  238.        
  239. #define uchar unsigned char
  240. #define uint  unsigned int

  241. #define DATA_PORT  P1

  242. sbit LCD_RS = P0^0;
  243. sbit LCD_RW = P0^1;
  244. sbit LCD_EN = P0^2;       


  245. /*******************************************************************

  246.   检查LCD忙状态  
  247.   lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。

  248. *******************************************************************/
  249. bit lcd_busy()
  250. {
  251.     bit result;
  252.     LCD_RS = 0;
  253.     LCD_RW = 1;
  254.     LCD_EN = 1;
  255.     delayNOP();
  256.     result = (bit)(DATA_PORT&0x80);
  257.     LCD_EN = 0;
  258.     return(result);
  259. }

  260. /*******************************************************************

  261.   写指令数据到LCD      
  262.   RS=L,RW=L,E=高脉冲,D0-D7=指令码。
  263.   Check=1,进行忙检测。

  264. *******************************************************************/
  265. void lcd_wcmd(uchar cmd, bit Check)
  266. {   
  267.     if(Check)
  268.     while(lcd_busy());

  269.     LCD_RS = 0;
  270.     LCD_RW = 0;
  271.     LCD_EN = 0;
  272.     delayNOP();
  273.     DATA_PORT = cmd;
  274.     delayNOP();
  275.     LCD_EN = 1;
  276.     delayNOP();
  277.     LCD_EN = 0;
  278. }

  279. /*******************************************************************

  280.   写显示数据到LCD
  281.   RS=H,RW=L,E=高脉冲,D0-D7=数据。

  282. *******************************************************************/
  283. void lcd_wdat(uchar dat)
  284. {                          
  285.     while(lcd_busy());      //进行忙检测

  286.     LCD_RS = 1;
  287.     LCD_RW = 0;
  288.     LCD_EN = 0;
  289.     DATA_PORT = dat;
  290.     delayNOP();
  291.     LCD_EN = 1;
  292.     delayNOP();
  293.     LCD_EN = 0;
  294. }

  295. /*******************************************************************

  296.   LCD初始化设定

  297. *******************************************************************/
  298. void lcd_init()
  299. {
  300.     delayms(50);
  301.     lcd_wcmd(0x38,0);      //16*2显示,5*7点阵,8位数据
  302.     delayms(5);
  303.     lcd_wcmd(0x38,0);      //不进行忙检测,强制执行。
  304.     delayms(5);
  305.     lcd_wcmd(0x38,0);
  306.     delayms(5);

  307.         lcd_wcmd(0x38,1);      //进行忙检测
  308.     delayms(5);
  309.     lcd_wcmd(0x0c,1);      //显示开,关光标
  310.     delayms(5);
  311.     lcd_wcmd(0x06,1);      //移动光标
  312.     delayms(5);
  313.     lcd_wcmd(0x01,1);      //清除LCD的显示内容
  314.     delayms(5);
  315. }

  316. /*******************************************************************

  317.   设定显示位置

  318. *******************************************************************/
  319. void lcd_pos_xy(uchar pos_x,uchar pos_y)
  320. {                          
  321.    uchar  pos_temp;

  322.    pos_temp=pos_x & 0x0f;
  323.    pos_y &= 0x0f;

  324.    if(pos_y==0x01)
  325.    pos_temp |= 0x80;
  326.    else
  327.    if(pos_y==0x02)
  328.    pos_temp |= 0xc0;

  329.    lcd_wcmd(pos_temp,1);
  330. }

  331. /*******************************************************************

  332.   写字符串子函数

  333. *******************************************************************/
  334. void  lcd_w_string(uchar pos_x,uchar pos_y,uchar code *str,uint times)
  335. {
  336.    uchar m;
  337.    lcd_pos_xy(pos_x,pos_y);      //设定起始位置
  338.    for(m=0; m<16; m++)
  339.    {
  340.      lcd_wdat(str[m]);
  341.          delayms(times);
  342.    }
  343. }

  344. /*****************************************************************

  345.   pos_x 取值范围: 0 - 15

  346.   pos_y 取值范围: 1 - 2

  347. ******************************************************************/



  348. #include
  349. #include "delay.h"
  350. #include "IIC.h"

  351. sbit SDA = P2^5;
  352. sbit SCL = P2^6;
  353.        
  354. /**********************************************************

  355. 启动子程序

  356. 在 SCL 高电平期间 SDA 发生负跳变

  357. **********************************************************/
  358. void I2C_start()
  359. {
  360.    SDA = 1;
  361.    SCL = 1;
  362.    delayNOP();
  363.    SDA = 0;
  364.    delayNOP();
  365.    SCL = 0;
  366. }

  367. /**********************************************************

  368. 停止子函数

  369. 在 SCL 高电平期间 SDA 发生正跳变

  370. **********************************************************/
  371. void I2C_stop()
  372. {
  373.    SDA = 0;
  374.    SCL = 1;
  375.    delayNOP();
  376.    SDA = 1;
  377.    delayNOP();
  378. }

  379. /**********************************************************

  380. 发送一个字节子程序

  381. **********************************************************/
  382. unsigned char I2C_write_byte(unsigned char indata)
  383. {
  384.     unsigned char i, ack;

  385.     // I2C 发送8 位数据
  386.    for (i=0; i<8; i++)
  387.    {
  388.      // 高在前低在后
  389.      if (indata & 0x80)
  390.       SDA = 1;
  391.      else
  392.       SDA = 0;

  393.      // 发送左移一位
  394.      indata <<= 1;
  395.      delayNOP();
  396.      SCL = 1;
  397.      delayNOP();
  398.      SCL = 0;
  399.    }

  400.     // 设置SDA为输入
  401.    SDA =1;;
  402.    delayNOP();

  403.     // 读取从机应答状态
  404.     SCL = 1;

  405.     delayNOP();

  406.     if(SDA)
  407.     {
  408.       ack = I2C_NACK;
  409.     }
  410.     else
  411.     {
  412.       ack = I2C_ACK;
  413.     }
  414.     SCL = 0;

  415.     return ack;
  416. }

  417. /**********************************************************

  418.   读一个字节子程序

  419. **********************************************************/
  420. unsigned char I2C_read_byte(unsigned char ack)
  421. {
  422.     unsigned char i, data1 = 0;

  423.     // SDA 设置输入方向
  424.     SDA = 1;

  425.     // I2C 接收8位数据
  426.     for(i = 8; i > 0; i--)
  427.     {
  428.       data1 <<= 1;
  429.       SCL = 1;
  430.       delayNOP();

  431.         // 高在前低在后
  432.         if (SDA)
  433.         {
  434.           data1++;
  435.                 }
  436.         SCL = 0;
  437.         delayNOP();
  438.     }

  439.     // 主机发送应答状态
  440.     if(ack == I2C_ACK)
  441.       SDA = 0;
  442.     else
  443.       SDA = 1;

  444.     delayNOP();
  445.     SCL = 1;
  446.     delayNOP();
  447.     SCL = 0;

  448.     return data1;
  449. }

  450. /*********************************************************/

回复评论 (5)

电路自己焊的还是画的PCB板?如果自己焊的,那么AT的不能工作是正常的,我以前也遇到过。
点赞  2013-11-21 10:34
首先注意资源上的差别,另外注意存储器选择脚一定要接Vcc,即选择片内程序存储器。
上传了一些书籍资料,也许有你想要的:https://download.eeworld.com.cn/user/chunyang
点赞  2013-11-21 16:46

回复 沙发jzffzj 的帖子

自己焊的,为什么不能工作?
点赞  2013-11-22 16:32

回复 板凳chunyang 的帖子

程序应该没什么问题吧,因为用STC能正常工作,也没超过AT的内存
点赞  2013-11-22 16:33

回复 5楼小杜在此 的帖子

仔细看器件手册,二者的资源有不同的地方。
上传了一些书籍资料,也许有你想要的:https://download.eeworld.com.cn/user/chunyang
点赞  2013-11-22 16:52
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复