找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 996|回复: 1
打印 上一主题 下一主题
收起左侧

求教一个MCU程序,这个功能难度真的实现不了吗?

[复制链接]
跳转到指定楼层
楼主
ID:190577 发表于 2019-11-13 07:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1、  时间继电器有四种模式即延时开模式、延时关模式、循环延时模式和复位模式。使用板载按键A的短按方式控制延时开模式,使用按键A的长按方式控制延时关模式;使用板载按键B的短按方式控制循环延时模式,使用按键B的长按方式控制复位模式。短按操作:按键按下,按下时间<1s,属于一次短按操作 ;长按操作:按键按下,按下时间>1s,属于一次长按操作。

2、使用板载按键C D键设定延时间隔,延时间隔初始化为0。延时间隔范围为0-99秒,C键设定个位秒,D键设定十位秒。每按一次C键增加1秒,每按一次D键增加10秒。延时间隔的精度为0.1秒(即使用处理器ATmega128的定时器/计数器的单位定时时间为0.1秒)。

3延时开模式指短按A键后,板载发光二极管LED1灭,在7段数码管或液晶显示屏上开始延时时间倒计时,倒计时到0,板载发光二极管LED1长亮;

延时关模式指长按A键后,发光二极管LED1长亮,在7段数码管或液晶显示屏上开始延时时间倒计时,倒计时到0LED1灭。

循环延时模式指短按B键后在第一个延时间隔内LED1闪烁显示,在下一个延时间隔内LED1长亮,如此交替进行,直至进入复位模式后停止。7段数码管或液晶显示屏上同时不断进行延时时间倒计时。

复位模式指长按B键后进入复位模式,LED1灭,在7段数码管或液晶显示屏上显示设定的延时间隔。

4、一种模式尚未完成要求变换另一种模式时,则当前模式完成后再更换,但任何一种模式下只要复位键按下,立即进入复位模式。
现在问题:模式切换功能还是没有实现,两种延时模式结束后不会跳到新的模式里;循环模式应该是一次闪烁一次长亮循环的,现在是两次长亮一次闪烁循环,两种延时模式结束后按A或短按B也不会进入新的模式

#include <macros.h>
#include <string.h>
#include <stdio.h>
#include <iom128v.h>
#define uchar unsigned char
#define uint  unsigned int
unsigned int t0_ovfnum;//t0软件定时计数器
#define RS_CLR PORTC &= ~(1 << PC0)                 //RS置低
#define RS_SET PORTC |= (1 << PC0)                  //RS置高
#define RW_CLR PORTC &= ~(1 << PC1)                 //RW置低
#define RW_SET PORTC |= (1 << PC1)                  //RW置高
#define EN_CLR PORTC &= ~(1 << PC2)                 //E置低
#define EN_SET PORTC |= (1 << PC2)                  //E置高
#define Data_IO         PORTA                //液晶数据口
#define Data_DDR        DDRA                 //数据口方向寄存器
uchar shi=0,ge=0;
uchar time;
uchar flag;
uchar num=1;
uchar flag_z=1;
uchar flag_s=1;
uint key_press_num=0;
/*******************************************
函数名称: Delayms
功    能: 延时指定毫秒(8M晶振)
参    数: MS--延时的毫秒数
返回值  : 无
/********************************************/
void delay_nms(uint MS)   
{
uint i,j;
for( i=0;i<MS;i++)
for(j=0;j<1141;j++); //1141是在8MHz晶振下,通过软件仿真反复实验得到的数值
}
//*************************************************************************
//   初始化子程序
//*************************************************************************
void system_init(void)
{
Data_IO = 0xFF;            //电平设置
Data_DDR = 0xFF;            //方向输出
PORTF = 0xFF;                       //电平设置
DDRF = 0xFF;                        //方向输出
    PORTD=0xFF;
DDRD=0x00;

}
//***********************************************************************
// 显示屏命令写入函数
//***********************************************************************

void LCD_write_com(unsigned char com)
{
RS_CLR;
RW_CLR;
EN_SET;
Data_IO = com;
delay_nms(5);
EN_CLR;
}
//***********************************************************************
// 显示屏数据写入函数
//***********************************************************************
void LCD_write_data(unsigned char data)
{
RS_SET;
RW_CLR;
EN_SET;
Data_IO = data;
delay_nms(5);
EN_CLR;
}
//***********************************************************************
// 显示屏清空显示
//***********************************************************************
void LCD_clear(void)
{
LCD_write_com(0x01);
delay_nms(5);
}
//***********************************************************************
// 显示屏字符串写入函数
//***********************************************************************
void LCD_write_str(unsigned char x,unsigned char y,unsigned char *s)
{

    if (y == 0)
    {
     LCD_write_com(0x80 + x);
    }
    if(y==1)
    {
     LCD_write_com(0x80+0x40+x);
    }
   
    while (*s)
    {
     LCD_write_data( *s);
     s ++;
    }
}
//***********************************************************************
// 显示屏单字符写入函数
//***********************************************************************
void LCD_write_char(unsigned char x,unsigned char y,unsigned char data)
{

    if (y == 0)
    {
     LCD_write_com(0x80 + x);
    }
    else
    {
     LCD_write_com(0xC0 + x);
    }
   
    LCD_write_data( data);  
}
void xs_d(unsigned char x,unsigned char y,unsigned int aa)
{
    if (y == 0)
    {
     LCD_write_com(0x80 + x);
    }
    else
    {
     LCD_write_com(0xC0 + x);
    }
    LCD_write_data('T');
LCD_write_data('i');
LCD_write_data('m');
LCD_write_data('e');
LCD_write_data(':');
LCD_write_data(aa/10+0x30);
LCD_write_data(aa%10+0x30);  
    LCD_write_data(' ');
LCD_write_data(' ');
LCD_write_data(' ');
LCD_write_data(' ');
LCD_write_data(' ');
LCD_write_data(' ');
LCD_write_data(' ');
LCD_write_data(' ');
LCD_write_data(' ');
LCD_write_data(' ');
      
}

//***********************************************************************
// 显示屏初始化函数
//***********************************************************************
void LCD_init(void)
{
DDRA = 0xFF;            //I/O口方向设置
DDRA |= (1 << PA5) | (1 << PA6) | (1 << PA7);
LCD_write_com(0x38);    //显示模式设置
delay_nms(5);
LCD_write_com(0x08);    //显示关闭
delay_nms(5);
    LCD_write_com(0x01);    //显示清屏
delay_nms(5);
    LCD_write_com(0x06);    //显示光标移动设置
delay_nms(5);
LCD_write_com(0x0C);    //显示开及光标设置
    delay_nms(5);
}
void timer0_init(void)//1ms
{
TCCR0 = 0x00; //stop
TCNT0 = 0xB2; //set count

   TIMSK |= 0x01; //timer interrupt sources
}
void key(void)//按键扫描
{
    static unsigned char i=0;
if(PIND==0xef)
{
  delay_nms(2);
  if(PIND==0xef)
  {
   while(PIND!=0xff)
   {
     key_press_num++;
     delay_nms(10);
     if(key_press_num==100)
     {
        key_press_num=0;
        while(PIND!=0xff)
     {
       PORTE=0x00;
     if(flag_z==1)
     {
           flag=2;  
     flag_z=0;
     }  
     }
     
     }  
     }
      TCCR0 = 0x05;
     if(flag==2)
     {}
     else
     {
   
   PORTE=0xff;
   if(flag_z==1)
   {
   flag=1;flag_z=0;
   }
   }
   }
}

if(PIND==0xdf)
{
  delay_nms(2);
  
     if(PIND==0xdf)
  {
   while(PIND!=0xff)
   {
     key_press_num++;
     delay_nms(10);
     if(key_press_num==100)
     {
        key_press_num=0;
        while(PIND!=0xff)
     {
        flag_z=1;
     if(flag==3)
     {flag_s=0;}
           flag=4;  
     TCCR0=0x00;
     time=10*shi+ge;
     
     
     }
        }
     if((flag==4)&&(flag_s==1))break;
     if(flag_z==1)
        {
   
          flag=3;
    flag_s=1;
          flag_z=0;
        }
        TCCR0=0x05;
     }  
    }
}
    if(PIND==0xbf)
{
  delay_nms(2);
  
     if(PIND==0xbf)
  {
   shi++;
   if(shi>9)
   shi=0;
     time=10*shi+ge;
   while(PIND!=0xff);
      
   }
}
  if(PIND==0x7f)
{
  delay_nms(2);
     if(PIND==0x7f)
  {
    ge++;
   if(ge>9)
   ge=0;
         
      time=10*shi+ge;
   while(PIND!=0xff);
      
   }
}

}

//*************************************************************************
//   主程序
//*************************************************************************
void main(void)
{
   system_init();                                //系统初始化,设置IO口属性
   delay_nms(10);                                //延时100ms
   LCD_init();                                   //液晶参数初始化设置
   DDRC=0xFF;                        //PC口上拉电阻使能
   PORTC=0xff;                       //PC高四位输入低四位输出
   DDRE=0xFF;                        //PC口上拉电阻使能
   PORTE=0xff;                       //PC高四位输入低四位输出
   timer0_init();
    _SEI(); //开全局中断
   while (1)
   {
  key();
  if(flag==3)
  {
     if(num==1)
    {
    PORTE=0xff;
    delay_nms(10);   
    PORTE=0x00;
    delay_nms(10);
    }  
    if(num==2)
     PORTE=0x00;
     if(time==0)
     {
        time=10*shi+ge;
      num++;
         if(num>2)
         num=1;
     }
  }
  if(flag==4)
  {
   PORTE=0xff;
   time=10*shi+ge;
  }
  xs_d(0,0,time);
      
  }
  
}
#pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF
void timer0_ovf_isr(void)
{
TCNT0 = 0xB2; //reload counter value
t0_ovfnum ++;
if(t0_ovfnum == 100)//100ms
{
  t0_ovfnum = 0;
  if(time>0)
  {
   time--;
  }
  else
  {
    TCCR0 =0; //stop
    flag_z=1;
    if(flag==1)
     PORTE=0x00;
    if(flag==2)
     PORTE=0xff;
         
   
  }
  
  
}
  

}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:245004 发表于 2019-11-13 20:52 | 只看该作者
显示函数如果正常,子函数不用贴出来,按键和主函数,中断里面的一些关键语句应该做上注释,虽然你的程序看起来不算复杂,但是别人也是不愿意花费太多时间研究你的程序,所以建议适当注释,这样你自己也容易发现问题,别人也能更快帮助你。
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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