2012-08-23 00:28:36 minidick 阅读数 670
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3397 人正在学习 去看看 朱有鹏

    第一次接触单片机c程序,写的代码竟然一直反复执行,实在是不能理解。问了同事才知道,一定要死循环,防止指令地址持续增加后会回到程序开头再次执行。

 

2019-01-09 21:41:03 lin5103151 阅读数 1154
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3397 人正在学习 去看看 朱有鹏

原理:此例程使用51单片机作为控制器,通过按键设定洗衣机的工作时间并用数码管显示工作时间,然后控制2个继电器循环工作状态,模拟洗衣机间歇正反转,一般正转3s,停止2s,然后反转3s,停止2s,循环上述动作。

程序如下

#define KeyPort P3

#define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换
sbit LATCH1=P2^2;//定义锁存使能端口 段锁存
sbit LATCH2=P2^3;//                 位锁存

sbit RELAY1 = P1^1;//定义继电器信号输出端口1
sbit RELAY2 = P1^2;//定义继电器信号输出端口2
/*------------------------------------------------
                  全局变量
------------------------------------------------*/
unsigned char hour,minute,second;//定义时分秒

bit UpdateTimeFlag;//定义读时间标志

unsigned char code dofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9
unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码
unsigned char TempData[8]; //存储显示值的全局变量
/*------------------------------------------------
                  函数声明
------------------------------------------------*/
void DelayUs2x(unsigned char t);//us级延时函数声明 
void DelayMs(unsigned char t); //ms级延时
void Display(unsigned char FirstBit,unsigned char Num);//数码管显示函数
unsigned char KeyScan(void);//键盘扫描
void Init_Timer0(void);//定时器初始化
void Stop(void);
void Clockwise (void);
void Anticlockwise(void);
/*------------------------------------------------
                    主函数
------------------------------------------------*/
void main (void)
{
unsigned char num;                  
Init_Timer0();    //初始化定时器0,主要用于数码管动态扫描
Stop();           //初始化洗衣机停止转动
while (1)         //主循环
  {
 num=KeyScan();    //循环调用按键扫描

 if(num==1)        //定时长度增加
   {
    if(minute<99)
	  minute++;
   }
 else if(num==2)   //定时长度减小
   {
    if(minute>0)
	  minute--;
   }
 if(UpdateTimeFlag==1)//定时刷新显示数据
   {
    UpdateTimeFlag=0;
	TempData[2]=dofly_DuanMa[minute/10];//分解显示信息,如要显示68,则68/10=6  68%10=8 
    TempData[3]=dofly_DuanMa[minute%10];//分解显示信息,如要显示68,则68/10=6  68%10=8  
    TempData[4]=0x40;
    TempData[5]=dofly_DuanMa[second/10];//分解显示信息,如要显示68,则68/10=6  68%10=8 
    TempData[6]=dofly_DuanMa[second%10];//分解显示信息,如要显示68,则68/10=6  68%10=8 

	if((minute==0)&&(second==0))//定时时间到,洗衣机停止转动
      {
      Stop();
      } 
	}
  }
}
/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
 while(--t);
}
/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{
     
 while(t--)
 {
     //大致延时1mS
     DelayUs2x(245);
	 DelayUs2x(245);
 }
}
/*------------------------------------------------
 显示函数,用于动态扫描数码管
 输入参数 FirstBit 表示需要显示的第一位,如赋值2表
 示从第三个数码管开始显示,如输入0表示从第一个显示。
 Num表示需要显示的位数,如需要显示99两位数值则该值
 输入2
------------------------------------------------*/
void Display(unsigned char FirstBit,unsigned char Num)
{
      static unsigned char i=0;
	  

	   DataPort=0;   //清空数据,防止有交替重影
       LATCH1=1;     //段锁存
       LATCH1=0;

       DataPort=dofly_WeiMa[i+FirstBit]; //取位码 
       LATCH2=1;     //位锁存
       LATCH2=0;

       DataPort=TempData[i]; //取显示数据,段码
       LATCH1=1;     //段锁存
       LATCH1=0;
       
	   i++;
       if(i==Num)
	      i=0;
}
/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/
void Init_Timer0(void)
{
 TMOD |= 0x01;	  //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响		     
 //TH0=0x00;	      //给定初值
 //TL0=0x00;
 EA=1;            //总中断打开
 ET0=1;           //定时器中断打开
 TR0=1;           //定时器开关打开
}
/*------------------------------------------------
                 定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1 
{
 static unsigned int num,i,times;
 TH0=(65536-2000)/256;		  //重新赋值 2ms
 TL0=(65536-2000)%256;
 
 Display(0,8);                // 调用数码管扫描
 i++;
 if(i==20)          //20ms更新一次
    {
	i=0;
	UpdateTimeFlag=1; //更新时间志位置1
	}
 num++;
 if(num==500)        //大致1s
   {
    num=0;
   
    ///////////////////////////////////////
	//执行正反转动作。
	switch(times)
	   {
	    case 1:Clockwise ();   break;//正转3s
		case 4:Stop();         break;//停止2s
		case 6:Anticlockwise();break;//反转3s
		case 9:Stop();         break;//停止2s
		case 11:times=0;       break;//清零循环上述动作
		default:break;
	   }
	times++;
   ///////////////////////////////////////////////////////
    if((minute!=0)||second)//如果分钟和秒都为0,不进行计时
       second--;//秒减1
    if(second==0xff)//如果=0后再减1则赋值59,即00过后显示59
	   {
	   second=59;
	   if(minute>0)//倒计时条件
	     {
	      minute--;
	      }

	   }
  }
}

/*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsigned char KeyScan(void)
{
 unsigned char keyvalue;
 if(KeyPort!=0xff)
   {
    DelayMs(10);
    if(KeyPort!=0xff)
	   {
	    keyvalue=KeyPort;
	    while(KeyPort!=0xff);
		switch(keyvalue)
		{
		 case 0xfe:return 1;break;
		 case 0xfd:return 2;break;
		 case 0xfb:return 3;break;
		 case 0xf7:return 4;break;
		 case 0xef:return 5;break;
		 case 0xdf:return 6;break;
		 case 0xbf:return 7;break;
		 case 0x7f:return 8;break;
		 default:return 0;break;
		}
	  }
   }
   return 0;
}

/*------------------------------------------------
                 顺时针转动
------------------------------------------------*/
void Clockwise (void)
{
 RELAY1=1;    //继电器1吸合,接通正向线圈
 RELAY2=0;
}
/*------------------------------------------------
                 逆时针转动
------------------------------------------------*/
void Anticlockwise(void)
{
  RELAY1=0;
  RELAY2=1;   //继电器2吸合,接通反向线圈
}

/*------------------------------------------------
                 停止转动
------------------------------------------------*/
void Stop(void)
{
  RELAY1=0;   
  RELAY2=0;
}

源码+AD电路图 下载:请关注公众号,首页回复“洗衣机”获取资料
在这里插入图片描述

2013-11-25 09:30:30 hxh129 阅读数 7212
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3397 人正在学习 去看看 朱有鹏

keil uvision2 教程 

在编定单片机程序的时候经常要用到keil uvision2 来编写程序,下面我们以AT89C51单片机为例,学习 如何使用keil uvision2 来编写程序。 keil uvision2 编写程序一般步骤如下: 

1. 新建工程 

2. 新建源程序文件,可以是C语言或汇编语言等 

3. 把源程序添加到工程中 

4. 编译并生成Hex文件 

下面开始我们的学习之旅吧!! 

一、新建工程 打开keil uvision2 软件,在菜单栏上选择project菜单下的new project (新建一个工程) 选择工程存储存位置,我们新建一文件夹,然后把工程保存在这一文件夹里面,保存之前先输入文件名如:how138 点击保存之后会弹出选择芯片对话框,我们要用的是AT89C51单片机,所以选择ATMEL公司的AT89C51单片机即可,然后单击确定。 软件会弹出提示框:问你是否添加默认代码,我们不需要所以选择否。 这样一个工程框加就建立好了。 

二、新建源程序文件(本例使用汇编语言) 选择菜单 File 下面的New (新建源程序文件) 在代码编辑框中输入代码如图所示,可以根据需要输入自已的代码 输入完成之后点击保存,并输入文件名:Text1.a (注意:要输入后缀名,因为是汇编所以使用a为后缀名),把文件保存在工程文件夹所在的目录里。 然后关才源程序编辑框,这一步完成。提示:如果用C语言编写则输入Text1.c后缀名为.c 

三、 把源程序添加到工程中 在文件列表里选择 Source Group 1 然后单击右键,在弹出的菜单里选择Add file to Group (添加源程序) 弹出选择源程序对话框,我们选择择文件类型为 *.s *.src *.a 这一项 然后找到第二步建立的源程序Text1.a 选择之后单击ADD按钮一次 最选择择关闭。此时源程序已经添加到工程中 在文件列表中可以看到 

四、 编译并生成Hex文件 接下来就是对源程序进行编译了,如果代码输入正确之后会提示编译成功。 程序写好并编译成功之后我们如何才能烧录到单片机里面呢??? 要把程序烧录到单片机里面,就必须先把它编译成Hex格式文件,所以下面我们学习如何建立HEX文件。 选单击按钮,在弹出的对话框中选择OUTPUT选项卡 在 Creat Hex 那一项前面打勾 (你还可以在NAME of executtable更改生成HEX的文件名) 其他选项按默认即可,最后单击确定 回到keil uvision2界面从新选择编译,就可以看到提示已经成功生成HEX文件。 到此为此已经成功的使用keil uvision2 来编写程序了,我们只要把HEX文件下载到单片机里面就可以完成了。

2019-06-03 15:54:22 threehecarim 阅读数 848
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3397 人正在学习 去看看 朱有鹏

ds18b20对时序要求很高,所以一定要注意延时

下面是32单片机的程序

//复位DS18B20
void DS18B20_Rst(void)	   
{                 
	DS18B20_IO_OUT(); 	//SET PG11 OUTPUT
    DS18B20_DQ_OUT=0; 	//拉低DQ
    delay_us(750);    	//延时750us
    DS18B20_DQ_OUT=1; 	//DQ=1 
	delay_us(15);     	//15US
}

//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
u8 DS18B20_Check(void) 	   
{   
	u8 retry=0;
	DS18B20_IO_IN();	//SET PG11 INPUT	 
    while (DS18B20_DQ_IN&&retry<200)
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=200)return 1;
	else retry=0;
    while (!DS18B20_DQ_IN&&retry<240)
	{
		retry++;
		delay_us(1);
	};
	if(retry>=240)return 1;	    
	return 0;
}

//从DS18B20读取一位
//返回1/0
u8 DS18B20_Read_Bit(void) 	 
{
    u8 data;
	DS18B20_IO_OUT();	//SET PG11 OUTPUT
    DS18B20_DQ_OUT=0; 
	delay_us(2);
    DS18B20_DQ_OUT=1; 
	DS18B20_IO_IN();	//SET PG11 INPUT
	delay_us(12);
	if(DS18B20_DQ_IN)data=1;
    else data=0;	 
    delay_us(50);           
    return data;
}

//从DS18B20读取一个字节
u8 DS18B20_Read_Byte(void)     
{        
    u8 i,j,dat;
    dat=0;
	for (i=1;i<=8;i++) 
	{
        j=DS18B20_Read_Bit();
        dat=(j<<7)|(dat>>1);
    }						    
    return dat;
}

//写一个字节到DS18B20
void DS18B20_Write_Byte(u8 dat)     
 {             
    u8 j;
    u8 testb;
	DS18B20_IO_OUT();	//SET PG11 OUTPUT;
    for (j=1;j<=8;j++) 
	{
        testb=dat&0x01;
        dat=dat>>1;
        if (testb) 
        {
            DS18B20_DQ_OUT=0;	// Write 1
            delay_us(2);                            
            DS18B20_DQ_OUT=1;
            delay_us(60);             
        }
        else 
        {
            DS18B20_DQ_OUT=0;	// Write 0
            delay_us(60);             
            DS18B20_DQ_OUT=1;
            delay_us(2);                          
        }
    }
}

//开始温度转换
void DS18B20_Start(void) 
{   						               
    DS18B20_Rst();	   
	DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);	// skip rom
    DS18B20_Write_Byte(0x44);	// convert
} 

//初始化DS18B20的DQ 同时检测DS18B20的存在
//返回1:不存在
//返回0:存在   	 
u8 DS18B20_Init(void)
{
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	
 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;		
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		  
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOC, &GPIO_InitStructure);

 	GPIO_SetBits(GPIOC,GPIO_Pin_10);    //拉高

	DS18B20_Rst();

	return DS18B20_Check();
}  

//从ds18b20得到温度值
//精度0.1C
short DS18B20_Get_Temp(void)
{
    u8 temp;
    u8 TL,TH;
	short tem;
    DS18B20_Start ();  			// ds1820 start convert
    DS18B20_Rst();
    DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);	// skip rom
    DS18B20_Write_Byte(0xbe);	// convert	    
    TL=DS18B20_Read_Byte(); 	// LSB 
    TH=DS18B20_Read_Byte(); 	// MSB  
		USART_SendData(USART1, TL);
		delay_ms(10);
		USART_SendData(USART1, TH);
	   	  
    if(TH>7)
    {
        TH=~TH;
        TL=~TL; 
        temp=0;					//温度为负
    }else temp=1;				//温度为正  	  
    tem=TH; 					
    tem<<=8;    
    tem+=TL;					
    tem=(float)tem*0.625;		
	if(temp)return tem; 	
	else return -tem;    
}

然后这里是51单片机的程序

这里我用的是12M晶振,延时程序如下

/*us延时,参数为1时约延时7us
			  10时约延时50us
			 100时约延时205us
			 250时约延时480us	
*/
void delay(uchar us) {
	while(us--);
}

然后下面就是对DQ信号线操作的程序

//复位ds18b20
void Init_ds18b20(void) {
	DQ = 1; 
	delay(1); 
	DQ = 0; 
	delay(250); 
	DQ = 1; 
	delay(100);
}

//读一个字节
uchar ReadoneByte() {
	uchar i;
	uchar dat = 0;
	for(i=8; i>0; i--) {
		DQ = 0;
		_nop_();
		dat >>= 1;
		DQ = 1;
		delay(1);
		if(DQ) dat |= 0x80;
		delay(10);
	}
	return dat;
}

//写一个字节
void WriteoneByte(uchar dat) {
	uchar i;
	for(i=8; i>0; i--) {
		DQ = 0;
		_nop_();
		DQ = dat & 0x01;
		delay(10);
		DQ = 1;
		dat >>= 1;
		delay(1);
	}
}

//获取温度值
int GetTempe() {
	int temp;
	uchar teml, temh;
	Init_ds18b20();
	WriteoneByte(0xcc);
	WriteoneByte(0x44);
	Init_ds18b20();
	WriteoneByte(0xcc);
	WriteoneByte(0xbe);
	teml = ReadoneByte();//先读低四位
	temh = ReadoneByte();//再读高四位
	
	temp = teml/16+temh*16;//这里只保留了整数,去掉了小数
	//temp <<= 8;
	//temp += teml;
	//t = temp * 0.625;
	return temp;
}

2015-08-22 22:19:38 h_xl88 阅读数 894
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3397 人正在学习 去看看 朱有鹏

单片机项目开发的一些心得

1:拿到项目需求后,需统计完成项目功能需要多少个IO口和其他的一些外设,另一项重要指标就是单片机系统的功耗问题;

2:完成第1步之后,进行单片机选型,此时除了考虑单片机的功能需要满足步骤1统计的要求之外,还需要考虑的问题是单片机的成本、供货最小批量以及供货周期;另外单片机选型的时候,还需要考虑产品升级,单片机资源应当有一定的冗余。对于程序开发者而言,选择的单片机品牌最好是自己熟悉的,这样可以加快项目的完成。

3:根据项目需求,设计电子电路原理图。原理图设计完成后,应当进行评审。评审可以避免一些原理上的错误,以及可以听取别人的建议和经验。

4:单片机程序设计人员需仔细阅读项目需求,画出编程流程图。好的流程图可以指导程序设计人员快速完成代码设计,并且方便程序的维护。

5:自测和测试。

没有更多推荐了,返回首页