Dnui_King 2023-05-27 09:31 采纳率: 100%
浏览 20
已结题

单片机报错,I2C.c文件的相关问题

*** ERROR L105: PUBLIC REFERS TO IGNORED SEGMENT

单片机 项目不知道哪里错了,上网搜说存储器模式改成大型就好了,但是改成大型之后生成的hex文件放进proteus里面CPU直接拉满,1602液晶屏也不显示,还一直发出刺啦刺啦的声音
如果不加上I2C.c那个文件是全部都没问题的,但是一加上I2C就会报一大堆WARNING,

/*-----------------------------------------------
  名称:智能温控系统
------------------------------------------------*/
/*-----------------------------------------------
处理器:STC90C516RD+ ,晶振11.0592M
------------------------------------------------*/

#include<reg52.h>             //包含头文件,包含特殊功能寄存器的定义
#include<stdio.h>
#include "ds1302.h"
#include "lcd1602.h"
#include "delay.h"
#include "uart.h"                ///////项目3中已完成///////
#include "18b20.h"
#include "i2c.h"

#define KEY_PORT (P3|0x1F)    //定义按键端口:P3口的后2位
#define KEY_ADD 0xBF            //按键ADD按下:10111111
#define KEY_DEC 0x7F            //按键DEC按下:01111111

bit ledFlag;                    //指示灯定时读取标志    /*-----项目4中新增-------*/
bit readtempFlag;                //温度定时读取标志    /*-----项目4中新增-------*/
bit readTimeFlag;                //时间定时读取标志
bit sendDataFlag;                //向上位机定时发送数据标志------项目3中新增加--------

unsigned char tempFlag;        //温度区域标志            /*-----项目4中新增-------*/
unsigned char modeFlag;        //定义工作模式:0正常,1设置年,2设置月,3设置日,4设置小时,5设置分钟,6设置温度上限,7设置温度下限

bit cmdFlag;                     //收到上位机命令标志,项目3中增加
unsigned char  idata cmdBuf[16];    //接收上位机指令缓冲区,项目3中增加
unsigned char idata sendBuf[16];    //定义串口发送缓冲区,项目3中增加
sbit LED0 = P1^0;                    //定义状态指示灯    /*-----项目4中新增-------*/
sbit SPEAKER = P1^2;                   //定义喇叭端口        /*-----项目4中新增-------*/
sbit RELAY1 = P2^2;                    //定义继电器信号输出端口1    /*-----项目4中新增-------*/
sbit RELAY2 = P2^3;                    //定义继电器信号输出端口2    /*-----项目4中新增-------*/

void Init_Timer0(void);            //定时器初始化
unsigned char Key_Scan(void);    //键盘扫描

void Alarm(unsigned int count);    //报警控制函数        /*-----项目4中新增-------*/
//设备开关控制函数(relay1-加热器/relay2-制冷器,flag=1继电器开/=0继电器关)
void Device(unsigned int relay,unsigned int flag);    /*-----项目4中新增-------*/

/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/
void Init_Timer0(void)
{
    ///////项目2中已完成:对定时器T0初始化///////
    TMOD |=0x01;
    TH0=(65536-2000)/256;
     TL0=(65536-2000)/256;
    EA=1;
    ET0=1;
    TR0=1;
}
/*------------------------------------------------
                 定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1 
{
    unsigned int num = 0;

    ///////项目2中已完成:每秒钟设置一次变量readTimeFlag为1////////

        TH0=(65536-2000)/256;     //2ms

        TL0=(65536-2000)%256;  
    
        num++;
        if(num%500==0)   //每隔500次 即一秒钟进行读时间标志位置1,用于定时读取ds1302时间
        {
          readTimeFlag=1;
        }

    /*--------待完善1:每秒钟设置一次变量readtempFlag为1,读温度-------*/
    //注意:此处必须+暂时关闭定时器,防止18b20被干扰时序

        if(num%500==0)
        {
            readtempFlag=1;
            TR0=0;
        }


    /*--------待完善2:-------*/
    //以下情况开启状态指示灯ledFlag,且状态指示灯闪烁的频率不同
    if((tempFlag==3)&&(num%500==0))    ledFlag=1; //指示灯标志位置1 
    else if (((tempFlag==2)||(tempFlag==4))&&(num%250==0)) ledFlag=1;//等级2或等级4
    else if (((tempFlag==1)||(tempFlag==5))&&(num%100==0)) ledFlag=1;//等级1或等级5

    ///////项目3中已完成:每10秒设置一次变量sendDataFlag为1///////

    if(num==5000)
    {
        num=0;
        sendDataFlag=1;
    }

}

/*------------------------------------------------
按键初始化函数
------------------------------------------------*/
void Key_Init(void)
{
        ///////项目1中已完成////////
       EX0=1;  //外部中断0打开
     IT0=1;  //边沿触发
      EA=1;   //打开总中断
 
}

/*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsigned char Key_Scan(void)
{
    //如果有按键返回键码,如果没有按键返回0xFF 
    ///////项目1中已完成////////
    unsigned char keyValue = 0;
    if(KEY_PORT!=0xFF)
    {
        DelayMs(10);
        if(KEY_PORT!=0xFF)
        {
            keyValue = KEY_PORT;
            while(KEY_PORT!=0xFF);
            return keyValue;
        }
    }
    return 0;
}

/*------------------------------------------------
外部中断INT0函数
------------------------------------------------*/
void KEY_SER (void) interrupt 0 //按键中断服务程序
{
    ///////项目1中已完成////////
    modeFlag++;
    if(modeFlag>=8)
    {
        modeFlag=0;
        LCD_Clear();
    }
    
} 

/*------------------------------------------------
                  串口中断程序
------------------------------------------------*/
void UART_SER(void) interrupt 4//串行中断服务程序
{
    unsigned char i;//接收长度变量
    unsigned char tmp;          //存储接收字符

    if(RI)                         //接收中断
    {
        ///////项目3中已完成:接收满足条件的字符到cmdBuf///////
        RI = 0;
        tmp=SBUF;

        if(tmp=='$'){
            cmdBuf[0] = tmp;
            i=1;
         }
        else if (tmp!='!'){
            cmdBuf[i]= tmp;
             i++;
            if(i>=16)
             i=0;      //连续接收最多16个字符信息
         }
         else
         {
                 cmdBuf[i+1]='0';
                i=0;
                cmdFlag=1;   //接收标志位置1
                UART_SendStr("OK");
         }
    }
} 

//报警控制函数
void Alarm(unsigned int count)
{
    unsigned char i;
    while(count>0)
    {
        for(i=0;i<200;i++)
        {
            DelayUs2x(200); 
            SPEAKER=!SPEAKER;
        }
        SPEAKER=0;//防止一直给喇叭通电造成损坏

       DelayMs(200);

        count--;
    }    
}

//继电器控制外设开关:flag 高电平有效
void Device(unsigned int relay,unsigned int flag)
{
    /*--------待完善3:根据relay和flag的状态,控制响应继电器动作-------*/
    if ((relay==1)&&(flag==0))  RELAY1 = 0;            //relay1关
    else if ((relay==1)&&(flag==1))  RELAY1 = 1;        //relay1开
        else if ((relay==2)&&(flag==0))  RELAY2 = 0;    //relay2关
            else if ((relay==2)&&(flag==1))  RELAY2 = 1;//relay2开
                else return;
}

/*------------------------------------------------
                    主函数
------------------------------------------------*/
void main (void)
{                  
    unsigned char tempH,tempL;                //温度阈值上限、下限
//    float temp;                                    //当前温度(项目3使用)    
    int  temp;                                    //当前温度:转换前                    /*-----项目4中新增-------*/
    float temperature;                        //当前温度:转换后                    /*-----项目4中新增-------*/
    float cur_temp;                            //当前温度:用于显示、串口发送    /*-----项目4中新增-------*/

    unsigned char display_data[16];        //定义显示区域缓冲区
    unsigned char key;                        //当前按键键值
    unsigned char i;
    unsigned char num=0;

    LCD_Init();          //初始化液晶
    LCD_Clear();         //清屏
    Init_Timer0();            //初始化定时器
    Key_Init();                //初始化按键中断

    Ds1302_Init();            //初始化时钟模块
    Lcd_User_Chr();      //写入自定义字符:摄氏度符号
    DelayMs(10);           //适当延时有助于稳定
    
    //初始化温度阈值
    tempL = 10;
    tempH = 30;
    
    //设置虚拟温度
//    temp = 25.50;

    //////项目2中增加的四行代码//////
    Ds1302_Read_Time();                               //首次读取时间
    if((cur_time_buf[2]+cur_time_buf[7])==0)     //无效数据,重设初始值
        Ds1302_Write_Time();        
        DelayMs(10);
    
    while (1)                 //主循环
    {
        //1-读取系统时间并显示//////项目2中已完成:读取实时时间//////
        if(readTimeFlag==1)    
        {
            //读取时间
            readTimeFlag=0;          //标志位清零
            Ds1302_Read_Time();    //读取时间参数
            
            //显示时间
            sprintf(display_data,"20%2d-%02d-%02d %02d:%02d",
                    (int)cur_time_buf[1],(int)cur_time_buf[2],(int)cur_time_buf[3],
                        (int)cur_time_buf[4],(int)cur_time_buf[5]);//年月日时分
            LCD_Write_String(0,0,display_data);//显示第一行
        }
        
/*        //2-显示温度和温度阈值(项目3中使用)
        sprintf(display_data,"T%2.2f",temp);//格式化温度值
        LCD_Write_String(0,1,display_data);//显示在第二行
        LCD_Write_Char(6,1,0x01);//写入温度右上角点
        LCD_Write_Char(7,1,'C'); //写入字符C
        sprintf(display_data,"L%2d H%2d",(int)tempL,(int)tempH);
        LCD_Write_String(9,1,display_data);        
*/        

        //2-读取温度并显示
        if(readtempFlag==1)
        {
            readtempFlag=0;
            //2-1读取温度并转换,注意:转换完之后重新开启定时器
            /*--------待完善4:-------*/        
            temp=ReadTemperature();
            temperature= temp*0.0625; //实际温度转化
            TR0=1;
            
            temp>>=4;
            if((temperature<0)||(temperature>80)) continue;
            
            //2-2显示温度及温度符号
            /*--------待完善5:-------*/
            cur_temp = temperature;
            sprintf(display_data,"T%2.2f",cur_temp);
            LCD_Write_String(0,1,display_data);//显示在第二行
            LCD_Write_Char(6,1,0x01);//写入温度右上角点
            LCD_Write_Char(7,1,'C'); //写入字符C

            //2-3判定温度区域
            /*--------待完善6:参考表P4-2,设置tempFlag为1-5-------*/
            if(temp<tempL-5)
                tempFlag=1;
            else if(temp<=tempL)
                tempFlag=2;
            else if(temp<=tempH)
                tempFlag=3;
            else if(temp<=tempH+5)
                tempFlag=4;
            else if(temp>tempH+5)
                tempFlag=5;
            //2-4五温度区域处理:外设控制
            /*--------待完善7:根据tempFlag的不同状态,设置不同的警报提示-------*/
            switch(tempFlag)
            {
                case 1:
                    LCD_Write_String(9,1,"    !!");  //报警
                    Alarm(1);
                break;
                case 2:
                    LCD_Write_String(9,1,"    !");  
                    Device(1,0);            //开启加热设备
                break;
                case 3:
                    sprintf(display_data,"L%2d H%2d",(int)tempL,(int)tempH);
                    LCD_Write_String(9,1,display_data);
                    Device(1,1);            //关闭加热设备
                    Device(2,1);            //关闭制冷设备
                break;
                case 4:
                    LCD_Write_String(9,1,"     !");
                    Device(2,0);            //开启制冷设备
                break;
                case 5:
                    LCD_Write_String(9,1,"     !");
                    Alarm(1);            //报警
                break;
                default:break;
            }
        }
        //状态指示灯控制    
        /*--------待完善8:如果ledFlag置位,开启状态指示灯-------*/
        if(ledFlag)
        {
            ledFlag=0;
            LED0=!LED0;
        }


        //3-设置模式下检测按键:调整时间、温度阈值设定等        
        while(modeFlag!=0)    //进入调节模式,直到恢复正常模式
        {
            key=Key_Scan();
            if (key!=0xFF)        //如果检测到ADD/DEC按键按下
            {
                switch(modeFlag)
                {
                    case 1:                //调年    
                            if((key==KEY_ADD)&&(cur_time_buf[1]<99))    cur_time_buf[1]++;
                            else if((key==KEY_DEC)&&(cur_time_buf[1]>0)) cur_time_buf[1]--;
                            LCD_Clear();
                            sprintf(display_data,"20%2d",(int)cur_time_buf[1]);
                            LCD_Write_String(0,0,display_data);//显示年
                            Ds1302_Write_Time();                    
                    break;
                    case 2:                //调月    
                            ///////项目1中已完成////////
                            if((key==KEY_ADD)&&(cur_time_buf[2]<12))    cur_time_buf[2]++;
                            else if((key==KEY_DEC)&&(cur_time_buf[2]>1)) cur_time_buf[2]--;
                            LCD_Clear();
                            sprintf(display_data,"%2d",(int)cur_time_buf[2]);
                            LCD_Write_String(5,0,display_data);//显示年
                            Ds1302_Write_Time();
                            
                    break;                
                    case 3:                //调日    
                            if((key==KEY_ADD)&&(cur_time_buf[3]<31))    cur_time_buf[3]++;
                            else if((key==KEY_DEC)&&(cur_time_buf[3]>1)) cur_time_buf[3]--;
                            LCD_Clear();                            
                            sprintf(display_data,"%2d",(int)cur_time_buf[3]);
                            LCD_Write_String(8,0,display_data);//显示日        
                            Ds1302_Write_Time();                            
                    break;    
                    case 4:                //调时    
                            if((key==KEY_ADD)&&(cur_time_buf[4]<23))    cur_time_buf[4]++;
                            else if((key==KEY_DEC)&&(cur_time_buf[4]>0)) cur_time_buf[4]--;
                            LCD_Clear();                            
                            sprintf(display_data,"%2d",(int)cur_time_buf[4]);
                            LCD_Write_String(11,0,display_data);//显示时    
                            Ds1302_Write_Time();                            
                    break;    
                    case 5:                //调分    
                            ///////项目1中已完成////////
                            if((key==KEY_ADD)&&(cur_time_buf[5]<59))    cur_time_buf[5]++;
                            else if((key==KEY_DEC)&&(cur_time_buf[5]>0)) cur_time_buf[5]--;
                            LCD_Clear();                            
                            sprintf(display_data,"%2d",(int)cur_time_buf[5]);
                            LCD_Write_String(14,0,display_data);//显示时    
                            Ds1302_Write_Time();                
                        
                    break;    
                    case 6:                //调温度阈值上限    
                            if((key==KEY_ADD)&&(tempH<50)) tempH++;        //调上限+1
                                else if((key==KEY_DEC)&&(tempH>tempL)) tempH--;        //上限-1
                            LCD_Clear();                            
                            sprintf(display_data,"Temp H:%2d (L:%2d)",(int)tempH,(int)tempL);
                            LCD_Write_String(0,1,display_data);    //显示分            
                    break;    
                    case 7:                //调温度阈值下限    
                            ///////项目1中已完成////////
                            if((key==KEY_ADD)&&(tempL<tempH)) tempL++;        //调下限+1
                            else if((key==KEY_DEC)&&(tempL>0)) tempL--;        //下限-1
                            LCD_Clear();                            
                            sprintf(display_data,"Temp L:%2d (H:%2d)",(int)tempL,(int)tempH);
                            LCD_Write_String(0,1,display_data);    //显示                
                    break;                    
                }//end of switch
            }
            DelayMs(20); 
        }    //end of mode while
        
        //4-发送串口数据信息给上位机
        ///////项目3中已完成:满足发送条件时,按照表P3-2的协议格式///////

        if(sendDataFlag)
        {      
                sendDataFlag = 0;
                sprintf(sendBuf,"20%2d-%02d %02d:%02d",
                            (int)cur_time_buf[1],(int)cur_time_buf[2],
                            (int)cur_time_buf[3],(int)cur_time_buf[4],(int)cur_time_buf[5]);//年月日时分
                UART_SendStr(sendBuf);
                UART_SendStr("\r\n");
                 sprintf(sendBuf,"T%2.2f%C L%2d H%2d\r",cur_temp,(int)tempL,(int)tempH);//格式化温度
                UART_SendStr(sendBuf);
                UART_SendStr("\r\n"); 
            }
        //5-接收串口命令:更新时钟、温度阈值设定、外设控制
        
         if(cmdFlag)
         {
             cmdFlag=0;
            switch(cmdBuf[1])
            {
                case 'D':
                    for(i=0;i<=3;i++)
                    {
                        cur_time_buf[i]=(cmdBuf[2*i+3]-0x30)*10+(cmdBuf[2*i+1+3]-0x30);
                    }//数据整合,如2个数 1和5整合成15
                    Ds1302_Write_Time();        
                    break;
                case 'T':                    
                    for(i=0;i<=1;i++)
                    {
                        cur_time_buf[i+4]=(cmdBuf[2*i+3]-0x30)*10+(cmdBuf[2*i+1+3]-0x30);/*^^^^^^^^^待完善处8:^^^^^^^^*/
                    }//数据整合,如2个数 1和5整合成15
                    Ds1302_Write_Time();        
                    break;
                case 'H':                    
                    temp=(cmdBuf[3]-0x30)*10+(cmdBuf[4]-0x30);
                    tempH=temp;            
                    break;
                case 'L':                
                    temp=(cmdBuf[3]-0x30)*10+(cmdBuf[4]-0x30);/*^^^^^^^^^待完善处9:^^^^^^^^*/
                    tempL=temp;
                    break;    
                default:
                    break;
            }
        }

        DelayMs(10); 
    
    }//end of while

    
}



![img](https://img-mid.csdnimg.cn/release/static/image/mid/ask/623279051586172.png "#left")
![img](https://img-mid.csdnimg.cn/release/static/image/mid/ask/144389051586138.png "#left")



img

  • 写回答

2条回答 默认 最新

  • qllaoda 2023-05-27 09:49
    关注

    C51的函数,如果在中断和普通函数里都会调用,要标记为可重入。而标记为可重入只是解决软件上的问题,逻辑上的冲突因为无法避免。所以最好不要出现这种情况

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 5月4日
  • 已采纳回答 5月4日
  • 创建了问题 5月27日

悬赏问题

  • ¥15 phython如何实现以下功能?查找同一用户名的消费金额合并—
  • ¥15 孟德尔随机化怎样画共定位分析图
  • ¥18 模拟电路问题解答有偿速度
  • ¥15 CST仿真别人的模型结果仿真结果S参数完全不对
  • ¥15 误删注册表文件致win10无法开启
  • ¥15 请问在阿里云服务器中怎么利用数据库制作网站
  • ¥60 ESP32怎么烧录自启动程序
  • ¥50 html2canvas超出滚动条不显示
  • ¥15 java业务性能问题求解(sql,业务设计相关)
  • ¥15 52810 尾椎c三个a 写蓝牙地址