⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pwm.c

📁 利用VHDL语言实现FPGA的PWM输出波形
💻 C
字号:
#include <reg52.h>
#include <intrins.h>//包含_nop()函数



#define uchar unsigned char
#define uint  unsigned int

sbit Dat=P1^0;  //595数据输入端
sbit Sclk=P1^2; //595上升沿输出端
sbit Lclk=P1^1;//595存储寄存器输入

sbit output=P3^5;
sfr P3M0=0xb1;//STC单片机强上拉推挽模式,在此模式下,系统自动设置为强上拉
sfr P3M1=0Xb2;
/*SFR0xb0为特殊功能寄存器的P3口地址,0xb1,0xb2为功能设置位*/

uchar code BitTab[4]={0x0e,0x0d,0x0b,0x07};//数码管位选择(00001110,00001101,00001011,00000111)
uchar code DispTab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
                      0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff};  //数码管字符显示

uchar temp1=0;
uchar temp2=0;
uchar keyvalue;
uchar scanf=0;
uchar chuli=0;
uchar keyci=0;
uchar DispT1=0;
uchar DispT2=0;
uchar DispT3=0;
uchar scanT=0x88;
uchar ydc=0;
uchar yfc=0;
uchar yec=0;
uchar shezhi=0;
uchar shezhif;
uchar timeflag;
uchar time;
uchar Aba=0;
uchar Abb=0;
uchar Bbb=8;
uchar Cbb=1;
uchar aim1=0;
uchar aim2=0;
uchar aim3=0;
uchar ain1=0;
uchar ain2=0;
uchar ain3=0;
uchar Hpl=0;
uchar Lpl=0;
uchar Hf=0;
uchar Lf=0;
uchar Hcishu=0;
uchar Lcishu=0;
uchar yhc=0;yic=0;yjc=0;ykc=0;ylc=0;ymc=0; //变量定义

void SendData(uchar SendDat1,uchar SendDat2) //595发送数据
{
  uchar i;
  uchar j;
  Lclk=0;//低电平时,数据更新
  for(i=0;i<8;i++)
  {
    Sclk=0;//低电平时,读数据
     for(j=8;j>0;j--);//短延时
   if((SendDat1&0x80)==0)
     Dat=0;
   else Dat=1;
   Sclk=1;//数据更新完成
    for(j=8;j>0;j--);
   SendDat1=SendDat1<<1;
  }
 
  for(i=0;i<8;i++)
  {
    Sclk=0;
    for(j=8;j>0;j--);
   if((SendDat2&0x80)==0)
     Dat=0;
   else Dat=1;
   Sclk=1;
    for(j=8;j>0;j--);
   SendDat2=SendDat2<<1;
   
   }
 Lclk=1;//上升沿数据发送
  
    for(j=8;j>0;j--);
     Lclk=0;
}

void Disp1()
{
	if(temp1<50)
	{
    	  SendData(BitTab[keyci-1],DispT1);
	}
	if(temp1>=50)
	{
	  SendData(0xff,0xc0);
	}
	if(temp1==100)
	{
	  temp1=0;
	}//字符闪烁
	SendData(BitTab[keyci],DispT2);
	SendData(BitTab[keyci+1],DispT3);//修改后不闪烁位字符不变
}
void Disp2()
{
	if(temp1<50)
	{
    	  SendData(BitTab[keyci-1],DispT2);
	}
	if(temp1>=50)
	{
	  SendData(0xff,0xc0);
	}
	if(temp1==100)
	{
	  temp1=0;
	}
        SendData(BitTab[keyci-2],DispT1);
	SendData(BitTab[keyci],DispT3);
}
void Disp3()
{
	if(temp1<50)
	{
    	  SendData(BitTab[keyci-1],DispT3);
	}
	if(temp1>=50)
	{
	  SendData(0xff,0xc0);
	}
	if(temp1==100)
	{
	  temp1=0;
	}
        SendData(BitTab[keyci-3],DispT1);
	SendData(BitTab[keyci-2],DispT2);
}
void Disp4()
{  
   if(timeflag==0)
   {
      SendData(BitTab[0],DispTab[Abb]);
      SendData(BitTab[1],DispTab[Bbb]);
      SendData(BitTab[2],DispTab[Cbb]);
   }//倒计时结束或者停止键按下后数码管显示当前值。
   if(timeflag==1)
   {
      SendData(BitTab[Aba],DispTab[Abb]);
      SendData(BitTab[Aba+1],DispTab[Bbb]);
      SendData(BitTab[Aba+2],DispTab[Cbb]);
      SendData(BitTab[Aba+3],0x88);
      if(time==200)//倒计时,5ms扫描一次,200次为一秒
      {
        time=0;//每1秒更新数据
	if(Abb==0)
	{
	    Abb=10;
	    if(Bbb==0)
	    {
	       Bbb=10;
               Cbb=0;
	    }
	    Bbb--;
	}
	Abb--;
        if((Abb==0)&&(Bbb==0)&&(Cbb==0)) //数码管全为0后置停止标志位
        {
	    timeflag=0;
	}
     }
  }
}
void scan()
{
    uchar key;
    if(shezhi!=0)//设置键按下后才可以扫描光标和+,-键
    {
    SendData(0x67,scanT); //矩阵键盘扫描方法,发第一行01100111,重要的是第四个0
    P1=P1|0x18;
    key=P1;
    key=key&0x18;//保护现场,读键值
    if(key!=0x18)
    {
    	temp2++;
	if((temp2==50)&&(key!=0x18))//去键盘抖动
        {
	   temp2=0;
	   if(key==0x08)
	   {
	      chuli=1;
	      keyvalue=1;//光标键
	   }
	   if(key==0x10)
	   {
	      chuli=1;
	      keyvalue=2;//+键
	   }
	}
    }
    }
    SendData(0x57,scanT);//扫描第二行01010111,重要的是第三个0
    key=P1|0xe7;
    key=key&0x18;
    if(key!=0x18)
    {
    	temp2++;
	if((temp2==50)&&(key!=0x18))
        {
	   temp2=0;
	   if(shezhi!=0)
	   {if(key==0x08)
	   {
	      chuli=1;
	      keyvalue=3;//-键
	   }
	   }
	   if(timeflag==0)
	   {
	      if(key==0x10)
	      {
	         chuli=1;
	         keyvalue=4;//设置键
	      }
	   }
       }
    }
    SendData(0x37,scanT);//扫描第三行00110111,重要的是第二个0
    key=P1|0xe7;
    key=key&0x18;
    if(key!=0x18)
    {
    	temp2++;
	if((temp2==50)&&(key!=0x18))
        {
	   temp2=0;
	   if(key==0x08)
	   {
	      chuli=1;
	      keyvalue=5;//启动键
	   }
	   if(key==0x10)
	   {
	      chuli=1;
	      keyvalue=6;//停止键
	   }
        }
    }
}

void deal()//按键处理程序
{
 if(keyvalue==1)//光标键处理
 { 
    keyci++;
    if(keyci==1)//第一位
    {
        if(shezhi==1)//高电平时间
        {
            DispT1=DispTab[aim1];
            DispT2=DispTab[aim2];
            DispT3=DispTab[aim3];
            Disp1();
	}
        if(shezhi==2)//低电平时间
        {
            DispT1=DispTab[ain1];
            DispT2=DispTab[ain2];
            DispT3=DispTab[ain3];
            Disp1();
	}
	if(shezhi==3)//倒计时时间
	{
            DispT1=DispTab[Abb];
            DispT2=DispTab[Bbb];
            DispT3=DispTab[Cbb];
            Disp1();
	}
    }
    if(keyci==2)//第二位
    {
       if(shezhi==1)
       {   
          DispT2=DispTab[aim2];
       }
       if(shezhi==2)
       {   
          DispT2=DispTab[ain2];
       } 
       if(shezhi==3)
       {   
          DispT2=DispTab[Bbb];
       }
       Disp2();
    }
    if(keyci==3)//第三位
    {
       if(shezhi==1)
       {   
          DispT3=DispTab[aim3];
       }
       if(shezhi==2)
       {   
          DispT3=DispTab[ain3];
       } 
       if(shezhi==3)
       {   
          DispT3=DispTab[Cbb];
       }
       Disp3();
    }
    if(keyci==4)
    {keyci=1;}
 }
 if(keyvalue==2)//+键处理程序
 {
    if(keyci==1)
    {  
       if(shezhi==1)
       {
           yhc++;//按一次字符值+1
           if(yhc==10)
           {
              yhc=0;
           }
	   aim1=yhc;
           DispT1=DispTab[yhc];
           Disp1();
       }
       if(shezhi==2)
       {
           yic++;
           if(yic==10)
           {
              yic=0;
           }
	   ain1=yic;
           DispT1=DispTab[yic];
           Disp1();
       }
       if(shezhi==3)
       {
           yec++;
	   if(yec==10)
	   {
	      yec=0;
	   }
	   Abb=yec;
	   DispT1=DispTab[Abb];
           Disp1();
       }
    }
    if(keyci==2)
    {
      if(shezhi==1)
      {
          yjc++;
          if(yjc==10)
          {
             yjc=0;
          }
	  aim2=yjc;
          DispT2=DispTab[yjc];
          Disp2();
      }
      if(shezhi==2)
      {
          ykc++;
          if(ykc==10)
          {
             ykc=0;
          }
	  ain2=ykc;
          DispT2=DispTab[ykc];
          Disp2();
      }
      if(shezhi==3)
      {
         yfc++;
         if(yfc==8)
         {
            yfc=0;
         }
	 Bbb=yfc;
	 DispT2=DispTab[Bbb];
         Disp2();
      }
    }
    if(keyci==3)
    {
       if(shezhi==1)
       {
          if(ylc==6)
          {
             ylc=0;
          }
	  aim3=ylc;
          DispT3=DispTab[ylc];
	  ylc++;
          Disp3();
       }
       if(shezhi==2)
       {
          if(ymc==6)
          {
             ymc=0;
          }
	  ain3=ymc;
          DispT3=DispTab[ymc];
	  ymc++;
          Disp3();
       }
       if(shezhi==3)
       {
	  if(ydc==2)
          {
             ydc=0;
          }
	  Cbb=ydc;
	  DispT3=DispTab[Cbb];
	  Disp3();
	  ydc++;
       }
    }
 }
 if(keyvalue==3)//-键处理程序
 {
    if(keyci==1)
    {  
       if(shezhi==1)
       {
           DispT1=DispTab[yhc];
           aim1=yhc;
           if(yhc==0)
           {
              yhc=10;
           }
           yhc--;
           Disp1();
       }
       if(shezhi==2)
       {
           DispT1=DispTab[yic];
           ain1=yic;
           if(yic==0)
           {
              yic=10;
           }
           yic--;
           Disp1();
       }
       if(shezhi==3)
       {
	   if(yec==0)
	   {
	      yec=10;
	   }
	   yec--;
	   Abb=yec;
	   DispT1=DispTab[Abb];
           Disp1();
       }
    }
    if(keyci==2)
    {  
       if(shezhi==1)
       {
          DispT2=DispTab[yjc];
	  aim2=yjc;
          if(yjc==0)
          {
             yjc=10;
          }
	  Disp2();
          yjc--;          
       }
       if(shezhi==2)
       {
          DispT2=DispTab[ykc];
	  ain2=ykc;
          if(ykc==0)
          {
             ykc=10;
          }
	  Disp2();
          ykc--;          
       }
       if(shezhi==3)
       {
          Bbb=yfc;
          DispT2=DispTab[Bbb];
	  if(yfc==0)
          {
              yfc=8;
          }
          Disp2();
	  yfc--;
       }
    }
    if(keyci==3)
    {
       if(shezhi==1)
       {
          if(ylc==0)
          {
             ylc=6;
          }
	  ylc--;
	  aim3=ylc;
          DispT3=DispTab[ylc];
	  Disp3();
       }
       if(shezhi==2)
       {
          if(ymc==0)
          {
             ymc=6;
          }
	  ymc--;
	  ain3=ymc;
          DispT3=DispTab[ymc];
	  Disp3();
       }
       if(shezhi==3)
       {
          if(ydc==0)
          {
             ydc=1;
          }
	  ydc--;
	  Cbb=ydc;
          DispT3=DispTab[Cbb];
	  Disp3();
       }
    }
 }
 if(keyvalue==4)//设置键
 {
    shezhi++;
    if(shezhi==4)
    {
      shezhi=1;
    }
    if(shezhi==3)
    {
      ylc=0;
      ymc=0;
    }
    switch(shezhi)
    { 
      case 1:scanT=0x89; break;
      case 2:scanT=0xcf; break;
      case 3:scanT=0xbf; break;
      default:break;//第四位控制,为H则为高电平设置时间,L为低电平设置时间,-为倒计时时间
    }
 }
 if(keyvalue==5)//启动键
 {
    shezhi=0;//设置状态归0
    keyci=0; //光标位置归0
    timeflag=1;//倒计时位置1
    time=0;
    Hcishu=0;
    Lcishu=0;
    Hpl=aim3*100+aim2*10+aim1;//计算高电平倒计时时间
    Lpl=ain3*100+ain2*10+ain1;//计算低电平倒计时时间
    ET1=1;//开定时器1中断
    Disp4();
 }
 if(keyvalue==6)
 {
    timeflag=0;//倒计时位置0,停止倒计时
    ET1=0;     //关定时器1中断
    Disp4();
 }
}
void main()
{
  P3M0=0x00;//00000000 
  P3M1=0x20;//00100000,设置为3.5受控,从右边数,第6位为P3.5位,设置为01,高电平推挽强上拉模式
  TMOD=0x11;
  ET0=1;
  TH0=(65536-5000)/256;//定时器0设置为5ms
  TL0=(65536-5000)%256;
  TH1=(65536-1000)/256;//定时器1设置为1ms
  TL1=(65536-1000)%256;
  TR0=1;
  TR1=1;
  EA=1;//定时器初始化
  output=0;
  while(1)
  {
    if(scanf==1)//扫描标志位
    {
      scanf=0;
      scan();
    }
   
    if(chuli==1)//处理标志位
    { 
      chuli=0;
      deal();
    }
    if(keyci==1)	           
    {Disp1();}
    if(keyci==2)
    {Disp2();}
    if(keyci==3)
    {Disp3();}
    if(shezhi==0)
    {Disp4();}
    if(timeflag==1)
    {
	if(Hf==1)//Hf=1时,发高电平
	{
	   output=1;
	}
	if(Lf==1)//Lf=1时,发低电平
	{
	   output=0;
	}
    }
  }
}

void Timer0() interrupt 1 using 1 
{
  TH0=(65536-5000)/256;
  TL0=(65536-5000)%256;
  scanf=1;
  temp1++;
  time++;
}

void Time1() interrupt 3 using 2
{
  TH1=(65536-1000)/256;
  TL1=(65536-1000)%256;
  Hcishu++;
  if(Hcishu<=Hpl)//高电平时,Hf=1
  {
     Hf=1;
  }
  if(Hcishu>Hpl)
  {
     Hf=0;
     Lcishu++;
     if(Lcishu<=Lpl)//低电平时,Lf=1
     {
        Lf=1;
     }
     if(Lcishu>Lpl)
     {
        Lf=0;
	Hcishu=0;
	Lcishu=0;
     }
  }
}
	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -