码迷,mamicode.com
首页 > 其他好文 > 详细

风扇控制系统--最终版

时间:2014-09-24 23:19:27      阅读:252      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   io   os   使用   ar   for   

风扇控制系统--最终版
简要描述: 
硬件线路连接=>硬件编程=>软件编程  
实现功能 :  
1、红外线遥控板 控制风扇开关 挡速
2、液晶显示器 显示风扇的工作情况
3、客户端 显示风扇工作情况
4、开启风扇时 记录上次的挡速
关键技术:         1、硬件中断         2、红外线通信         3、串口通信         4、FALSE存储

硬件截图:   bubuko.com,布布扣

bubuko.com,布布扣 


客户端软件截图:  bubuko.com,布布扣  
bubuko.com,布布扣
硬件编程源码:  
/********************************************************************
* 文件名  : FanServer.c
* 创建人  : wu_zhuojun,2014年2月23日 北京
* 版本号  : 3.0
***********************************************************************/
 
#include <reg51.h>
#include <intrins.h>
 
#define uchar unsigned char
#define uint  unsigned int
 
uchar LCD_ID_1[16] = {"I have a dream!"};
uchar LCD_ID_2[16] = {"Speed: 0"};
 
void delay(uchar x);  //x*0.14MS
void delay1(int ms);
void beep();
 
sbit IRIN = P3^3;         //红外接收器数据线
sbit BEEP = P1^5;         //蜂鸣器驱动线
sbit RELAY= P1^4;         //继电器驱动线
 
uchar IRCOM[7];
 
sbit E=P2^7; //1602使能引脚
sbit RW=P2^6; //1602读写引脚
sbit RS=P2^5; //1602数据/命令选择引脚
 
//==========直流电机参数定义 begin
sbit PWM = P1^0; //定义直流电机的控制端口
uchar PWM_ON = 0 ; //风扇档数
//==========直流电机参数定义 end
 
 
//==========FLASH参数定义 begin
sbit scl=P1^5;  //24c08 SCL
sbit sda=P3^6;  //24c08 SDA
//==========FLASH参数定义 End
 
/********************************************************************
* 名称 : delay()
* 功能 : 延时,延时时间大概为140US。
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Delay2()
{
int i,j;
for(i=0; i<=10; i++)
for(j=0; j<=2; j++)
;
}
 
 
/********************************************************************
* 名称 : enable(uchar del)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void enable(uchar del)
{
P0 = del;
RS = 0;
RW = 0;
E = 0;
Delay2();
E = 1;
Delay2();
}
 
/********************************************************************
* 名称 : write(uchar del)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void write(uchar del)
{
P0 = del;
RS = 1;
RW = 0;
E = 0;
Delay2();
E = 1;
Delay2();
}
 
/********************************************************************
* 名称 : L1602_init()
* 功能 : 1602初始化,请参考1602的资料
* 输入 : 无
* 输出 : 无
***********************************************************************/
void L1602_init(void)
{
enable(0x01);
enable(0x38);
enable(0x0c);
enable(0x06);
enable(0xd0);
}
 
/********************************************************************
* 名称 : L1602_char(uchar hang,uchar lie,char sign)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下
L1602_char(1,5,‘b‘)
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void L1602_char(uchar hang,uchar lie,char sign)
{
uchar a;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
enable(a);
write(sign);
}
 
/********************************************************************
* 名称 : L1602_string(uchar hang,uchar lie,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
L1602_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void L1602_string(uchar hang,uchar lie,uchar *p)
{
uchar a;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
enable(a);
while(1)
{
if(*p == ‘\0‘) break;
write(*p);
p++;
}
}
 
/********************************************************************
* 名称 : Com_Init()
* 功能 : 初始化串口程序,晶振11.0592, 波特率9600
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Com_Init(void)
{
TMOD = 0x20;
PCON = 0x00;
SCON = 0x50;
TH1 = 0xFd;
TL1 = 0xFd;
TR1 = 1;
}
 
//风扇3档
void PWM_Speed3()
{
static uchar status = 0;
if(10 > status)
{
PWM = 1;//风扇转
}
else//(1000 == status)
{
PWM = 0;//风扇不转
status = 0;
 
status++;
}
 
//风扇2档
void PWM_Speed2()
{
static uchar status = 0;
if(4 > status)
{
PWM = 1;//风扇转
}
else//(1000 == status)
{
PWM = 0;//风扇不转
status = 0;
 
status++;
}
 
//风扇1档
void PWM_Speed1()
{
static uchar status = 0;
if(0 == status)
{
PWM = 1;
}
else if(1 == status)
{
PWM = 1;
}
else //2 == status
{
PWM = 0;
status = 0;
status++;
}
 
//风扇0档
void PWM_Speed0()
{
PWM = 0;//风扇不转
}
 
/********************************************************************
* 名称 : PWM_Contrl()
* 功能 : 控制风扇的档数
* 输入 : 
* 输出 : 无
***********************************************************************/
void PWM_Contrl()
{
switch(PWM_ON)
{
case 0:
PWM_Speed0();
break;
case 1:
PWM_Speed1();
break;
case 2:
PWM_Speed2();
break;
case 3:
PWM_Speed3();
break;
default:
PWM_Speed0();
break;
}
}
 
 
/********************************************************************
* 名称 : flash()
* 功能 : 延时,时间为2个NOP,大概为2US
* 输入 : 无
* 输出 : 无
***********************************************************************/
void flash(void) 
{
_nop_();
_nop_();
}
 
/********************************************************************
* 名称 : x24c02_init()
* 功能 : 24c02初始化子程序
* 输入 : 无
* 输出 : 无
***********************************************************************/
void x24c02_init(void) 
{
scl = 1;
flash();
sda = 1;
flash();
}
 
/********************************************************************
* 名称 : start(void)
* 功能 : 启动I2C总线
* 输入 : 无
* 输出 : 无
***********************************************************************/
void start(void)
{
scl = 1; 
flash();
sda = 1;
flash(); 
sda = 0; 
flash(); 
scl = 0; 
flash();
}
 
/********************************************************************
* 名称 : stop()
* 功能 : 停止I2C总线
* 输入 : 无
* 输出 : 无
***********************************************************************/
void stop() 
{
scl = 0;
flash();
sda = 0; 
flash();
scl = 1;
flash();
sda = 1;
flash();
}
 
/********************************************************************
* 名称 : writex()
* 功能 : 写一个字节
* 输入 : j(需要写入的值)
* 输出 : 无
***********************************************************************/
void writex(uchar j)
{  
uchar i,temp;
temp = j;
for(i=0; i<8; i++)
{
scl = 0; 
flash(); 
sda = (bit)(temp & 0x80); 
flash();
scl = 1; 
flash();
temp = temp << 1; 
}
scl = 0;
flash(); 
}
 
/********************************************************************
* 名称 : readx()
* 功能 : 读一个字节
* 输入 : 无
* 输出 : 读出的值
***********************************************************************/
uchar readx(void)
{
uchar i, j, k = 0;
for(i=0; i<8; i++)
{
scl = 0;
flash();
if(sda == 1)
{
j = 1;
}
else j = 0;
k = (k << 1) | j; 
scl = 1;
flash();
return(k);
}
 
/********************************************************************
* 名称 : ack()
* 功能 : I2C总线时钟
* 输入 : 无
* 输出 : 无
***********************************************************************/
void ack(void)
{
uchar i = 0;
scl = 1;
flash();
while((sda == 1) && (i < 255)) 
{
i++;
}
scl = 0;
flash();
}
 
/********************************************************************
* 名称 : x24c02_read()
* 功能 : 从24c02中读出值
* 输入 : address(要在这个地址读取值)
* 输出 : 从24c02中读出的值
***********************************************************************/
uchar x24c02_read(uchar address)
{
uchar i;
start();
writex(0xa0);
ack();
writex(address);
ack();
start();
writex(0xa1);
ack();
i = readx();
stop();
return(i);
}
 
/********************************************************************
* 名称 : x24c02_write()
* 功能 : 想24c02中写入数据
* 输入 : address(地址) , info(值)
* 输出 : 无
***********************************************************************/
void x24c02_write(uchar address, uchar info)
{
start();
writex(0xa0);
ack();
writex(address);
ack();
writex(info);
ack();
stop();
}
 
 
/********************************************************************
* 名称 : main()
* 功能 : 
* 输入 : 无
* 输出 : 无
***********************************************************************/
main()
{
//=========初始化红外线控制 Begin=======//
IE = 0x84;                 //允许总中断中断,使能 INT1 外部中断
TCON = 0x10;               //触发方式为脉冲负边沿触发
 
IRIN=1;                    //I/O口初始化
BEEP=1;
RELAY=1; 
//=========初始化红外线控制 End=======//
 
delay1(10);                 //延时
L1602_init();               //初始化LCD
 
 
L1602_string(1, 1, LCD_ID_1);  //设置 液晶显示屏  显示LCD_ID_1的内容
L1602_string(2, 1, LCD_ID_2);  //设置 液晶显示屏  显示LCD_ID_2的内容
 
 
//=======初始化串口 Begin=======//
Com_Init();
//=======初始化串口 Begin=======//
 
//=======初始化FLASH Begin=======//
x24c02_init();         //初始化24C02
PWM_ON = x24c02_read(2); //读出保存的数据赋于sec
 
L1602_char(2,8,PWM_ON+‘0‘);
//=======初始化FALSH End=======//
 
while(1)
{
PWM_Contrl();
}
 
} //end main
 
 
/********************************************************************
* 名称 : IR_IN interrupt 2 using 0
* 功能 : 接收红外线数据,并中断处理液晶屏显示
* 输入 : 无
* 输出 : 无
***********************************************************************/
void IR_IN() interrupt 2 using 0
{
//======初始化串口发送数据 变量  Begin=======//
uchar code strSpeed[][4] = {"0", "1", "2", "3" };  
uchar *p = strSpeed[0];  //初始化为 0 档
//======初始化串口发送数据 变量  End=======//
 
unsigned char j,k,N=0;
EX1 = 0;   
delay(15);
if (IRIN==1) 
EX1 =1;
return;
//确认IR信号出现
while (!IRIN)            //等IR变为高电平,跳过9ms的前导低电平信号。
{
delay(1);
}
 
for (j=0;j<4;j++)         //收集四组数据
for (k=0;k<8;k++)        //每组数据有8位
{
while (IRIN)            //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
{
delay(1);
}
while (!IRIN)          //等 IR 变为高电平
{
delay(1);
}
while (IRIN)           //计算IR高电平时长
{
delay(1);
N++;           
if (N>=30)
EX1=1;
return;
} //if (N>=30)    //0.14ms计数过长自动离开。
} //while (IRIN)      //高电平计数完毕                
IRCOM[j]=IRCOM[j] >> 1;            //数据最高位补“0”
if (N>=8) 
{
IRCOM[j] = IRCOM[j] | 0x80;    //数据最高位补“1”
}  //if (N>=8)
N=0;
}//for (k=0;k<8;k++)
}//for (j=0;j<4;j++) 
 
if (IRCOM[2]!=~IRCOM[3])
EX1=1;
return; 
}
 
IRCOM[5]=IRCOM[2] & 0x0F;     //取键码的低四位
IRCOM[6]=IRCOM[2] >> 4;       //右移4次,高四位变为低四位
 
if(IRCOM[5]>9)
IRCOM[5]=IRCOM[5]+0x37;
}
else
IRCOM[5]=IRCOM[5]+0x30;
 
if(IRCOM[6]>9)
IRCOM[6]=IRCOM[6]+0x37;
}
else
IRCOM[6]=IRCOM[6]+0x30;
 
//=======控制 液晶显示屏显示数据 Begin=========//
 
if( (‘4‘ == IRCOM[6]) && (‘5‘ == IRCOM[5]))  //触发开关键
PWM_ON=0;//风扇关闭
//PWM_SLEEP = 0;
 
p = strSpeed[0];   //档速0
L1602_char(2,8,‘0‘);
}
else if( (‘0‘ == IRCOM[6]) && (‘C‘ == IRCOM[5]))  //触发1号键
{
PWM_ON=1;//风扇开启
//PWM_SLEEP=10;//风扇休眠时间
 
p = strSpeed[1];   //档速1
L1602_char(2,8,‘1‘);
}
else if( (‘1‘ == IRCOM[6]) && (‘8‘ == IRCOM[5]))  //触发2号键
{
PWM_ON=2;//风扇开启
//PWM_SLEEP=100;//风扇休眠时间
 
p = strSpeed[2];   //档速2
L1602_char(2,8,‘2‘);
}
else if( (‘5‘ == IRCOM[6]) && (‘E‘ == IRCOM[5]))  //触发3号键
{
PWM_ON=3;//风扇开启
//PWM_SLEEP=1000;//风扇休眠时间
p = strSpeed[3];   //档速3
L1602_char(2,8,‘3‘);
}
//=======控制 液晶显示屏显示数据 End=========//
 
 
//=======发送串口数据 Begin=========//
while(1)
{
SBUF = *p;
while(!TI)                   //如果发送完毕,硬件会置位TI
{
_nop_();
}
p++;
if(*p == ‘\0‘) break; //在每个字符串的最后,会有一个‘\0‘
TI = 0;                 //TI清零
}
//=======发送串口数据 End=========//
 
//beep();
EX1 = 1; 
 
//将风扇的档数记录
x24c02_write(2,PWM_ON);   //在24c08的地址2中写入数据sec
 
/**********************************************************/
void beep()
{
unsigned char i;
for (i=0;i<100;i++)
{
delay(4);
BEEP=!BEEP;                 //BEEP取反
BEEP=1;                      //关闭蜂鸣器
}  
/**********************************************************/
void delay(unsigned char x)    //x*0.14MS
{
unsigned char i;
while(x--)
{
for (i = 0; i<13; i++) {}
}
}
 
/**********************************************************/
void delay1(int ms)
{
unsigned char y;
while(ms--)
{
for(y = 0; y<250; y++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
 
软件编程部分源码:   
===================================================================================================
// FanDlg.h : 头文件
//
 
#pragma once
 
#define COM_RECVDATA WM_USER+1000//自定义消息
 
// CFanDlg 对话框
class CFanDlg : public CDialogEx
{
// 构造
public:
CFanDlg(CWnd* pParent = NULL); // 标准构造函数
 
// 对话框数据
enum { IDD = IDD_FAN_DIALOG };
 
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
 
private:
HANDLE hCom; //串口句柄
HANDLE hCommThread; //串口线程
 
public:
//获取串口句柄
HANDLE GetComHandle();
 
// 实现
protected:
HICON m_hIcon;
 
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
 
//打开串口
//返回值:TRUE 开启成功  FLASE 开启失败
BOOL OpenCom(CString strPort);
 
//接收到数据响应消息
afx_msg LRESULT OnRecvData(WPARAM wParam, LPARAM lParam);
 
public:
afx_msg void OnClose();
};
 
//声明 串口接收线程
extern DWORD WINAPI SerialPort1ThreadProcess(CFanDlg *pFan); ===================================================================================================  
 
// FanDlg.cpp : 实现文件
//
 
#include "stdafx.h"
#include "Fan.h"
#include "FanDlg.h"
#include "afxdialogex.h"
 
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
 
// CFanDlg 对话框
 
CFanDlg::CFanDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CFanDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
 
void CFanDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
 
BEGIN_MESSAGE_MAP(CFanDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_MESSAGE(COM_RECVDATA, &CFanDlg::OnRecvData)
ON_WM_CLOSE()
END_MESSAGE_MAP()
 
 
// CFanDlg 消息处理程序
 
BOOL CFanDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
 
this->SetWindowTextW(_T("风扇控制系统--客户端"));
 
// 将“关于...”菜单项添加到系统菜单中。
 
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
 
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
 
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
//  执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
 
// TODO: 在此添加额外的初始化代码
BOOL bStatu = OpenCom(_T("COM4"));
 
//启动串口监视线程
DWORD threadID;
hCommThread = ::CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,
  (LPTHREAD_START_ROUTINE)SerialPort1ThreadProcess, 
  this, 0, &threadID);
if (hCommThread == NULL)
{
::AfxMessageBox(_T("创建串口1处理线程失败"));
::PostQuitMessage(0);
}
 
 
return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}
 
BOOL CFanDlg::OpenCom(CString strPort)
{
       hCom=CreateFile(strPort,
              GENERIC_READ|GENERIC_WRITE, //允许读和写
              0, //独占方式
              NULL,
              OPEN_EXISTING, //打开而不是创建
              0, //同步方式
              NULL);
 
       if(hCom==(HANDLE)-1)
       {
            AfxMessageBox(_T("打开COM失败!"));
            return FALSE;
       }
 
   DCB wdcb;
   GetCommState (hCom, &wdcb);
   wdcb.BaudRate=9600;//波特率:9600,其他:不变
   if(!SetCommState (hCom, &wdcb))
   {
MessageBox(_T("串口设置出错!"));
return FALSE;
}
PurgeComm(hCom, PURGE_TXCLEAR);
 
       return TRUE;
}
 
 
 
void CFanDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
 
// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。
 
void CFanDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
 
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
 
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
 
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
 
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CFanDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
 
//接收数据后(通过监听线程发来的用户自定义消息)显示
LRESULT CFanDlg::OnRecvData(WPARAM wParam, LPARAM lParam)
{
CString recvStr((char *)wParam);
this->GetDlgItem(IDC_EDT_FAN_SPEED)->SetWindowTextW(recvStr + _T("级风速"));
UpdateData(false);
return TRUE;
}
 
HANDLE CFanDlg::GetComHandle()
{
return hCom; //串口句柄
}
 
//以一个线程不同监控串口行接收的数据
DWORD WINAPI SerialPort1ThreadProcess(CFanDlg *pFan)
{
char str[101];
DWORD wCount; //读取的字节数
while(TRUE)
{
ReadFile(pFan->GetComHandle(),str, 100, &wCount, NULL);
        if(wCount > 0) //收到数据
{
//发送消息给对话框主窗口,以进行接收内容的显示
str[wCount] = ‘\0‘;
::PostMessage(pFan->m_hWnd, COM_RECVDATA, (unsigned int) str, wCount); 
}
Sleep((DWORD)0.1);
}
return TRUE;
}
 
void CFanDlg::OnClose()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//CloseHandle(hCom);      //程序退出时关闭串口
 
CDialogEx::OnClose();
}
 
结束语: 快乐分享技术,每天进步一点。                                                                      2014.2.23  北京 

风扇控制系统--最终版

标签:style   blog   http   color   io   os   使用   ar   for   

原文地址:http://www.cnblogs.com/zhuojun/p/3991537.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!