电脑控制台灯(c# hook,显示室温,联网校正时间)
2013-11-24 19:36
477 查看
突发奇想,于是便写了一个小程序用于控制台灯,这几天功能也在不断的完善中,目前基本已经完成.下面进行功能的简述的代码的分析.
整体设计包含下位机程序和上位机程序.下位机用的c语言,上位机用的c# .功能显示见视频
整个系统功能包括:定时采集室温在电脑右下角显示,可联网校准电子时钟,可以电脑端快捷键控制台灯.视频中展示的顺序为
1,自动获取温度,图标动态显示室温 2,手动获取温度 3,按钮控制台灯 4 ,快捷键控制台灯 5,联网校准电子时钟 6最后展示
在任何界面只要按下快捷键便可以打开台灯(windows hook).
下面进行整个系统代码和原理的介绍.
下位机,
硬件上 ,包括 51单片机,ds1302,18b20,uln2003,pl2303 .硬件连接图如下:
下位机程序分析:
18b20.c
ds1302.c
串口部分程序没有比较好写,我便不贴上来了.程序往上位机传输数据时,我这里没有考虑负数.所以如果需要使用本程序需要注意这一点.
这个是下位机程序开发日志:
上位机程序分析,程序界面如图:
上位机程序有几个我自认为的亮点. 1,可以联网校准电子时钟. 2,可以在右下角显示温度 . 3,可以在任何状态下按下快捷键控制台灯.这里主要讲解这三部分功能.我这里把打包好的程序共享给大家,有需要源码的可以在下面留言.
亮点功能1,联系校准电子时钟:
这个功能代码我是参考下面[参考博客]部分的程序 ,实现了网络时间的获取,获取的格式为string 类型.这里如果想进行ds1302时间的设置,需要进行一下转码,方法如下:
亮点二,右下角动态显示温度
这个代码直接用的这个作者的http://www.codeproject.com/Articles/9361/WeatherNotify ,有兴趣的可以直接到这里查看.
亮点三,c# hook
代码参考第五条引用.原程序是有一点小错误,这里的更正方法如下:
在globalKeyboardHook.cs 文件中定义的委托下面添加这一句 private keyboardHookProc _keyboardHookProc; //新添加的
在 hook() 方法体中的代码更改为
如果想按下快捷键不对其它的程序产生影响,可以去掉这个方法体 public int hookProc(int code, int wParam, ref keyboardHookStruct lParam){}中的这一句
/*
if (kea.Handled)
return 1;
*/
好了,整个系统差不多介绍完了.虽然程序不太,但涉及到许多的知识 .需要上位机的源代码的可以留言.
博文为本人所写,转载请表明出处 电脑控制台灯
参考博客:
http://www.cnblogs.com/slyzly/articles/2108877.html
http://www.codeproject.com/Articles/9361/WeatherNotify
/article/5626604.html
http://bbs.csdn.net/topics/100169052
http://www.codeproject.com/Articles/19004/A-Simple-C-Global-Low-Level-Keyboard-Hook
整体设计包含下位机程序和上位机程序.下位机用的c语言,上位机用的c# .功能显示见视频
整个系统功能包括:定时采集室温在电脑右下角显示,可联网校准电子时钟,可以电脑端快捷键控制台灯.视频中展示的顺序为
1,自动获取温度,图标动态显示室温 2,手动获取温度 3,按钮控制台灯 4 ,快捷键控制台灯 5,联网校准电子时钟 6最后展示
在任何界面只要按下快捷键便可以打开台灯(windows hook).
下面进行整个系统代码和原理的介绍.
下位机,
硬件上 ,包括 51单片机,ds1302,18b20,uln2003,pl2303 .硬件连接图如下:
下位机程序分析:
/************************************************************************/ // 本程序作者 HennSun ,转载请表明出处. // /************************************************************************/ #include <reg52.h> #include "uart.h" #include "18b20.h" #include "ds1302.h" #define buff_size 5 sbit jdq=P1^0; sbit key_led=P3^3; unsigned int num; unsigned char control=0,set_time=0; unsigned char time[buff_size]; //用于设定时间 extern unsigned int temp; extern unsigned char flag_get; /*----------初始化定时器---------*/ void init_timer() { TMOD =0x01;//定时器设置 T0工作于方式1 16位 TH0=0xef; TL0=0xf0; ET0=1; //定时器 0 中断允许 . TR0=1; // run the timer0 这个中断会让单片机查询中断向量表. EA = 1; //打开总中断 } //显示 open 字符 void disp_open() { unsigned int i=400; while(i--) { P2=2; P0=0x3f; //'O' delay1(1); P0=0X00; P2=3; P0=0x73; //'P' delay1(1); P0=0X00; P2=4; P0=0x79; //'E' delay1(1); P0=0X00; P2=5; P0=0x37; //'N' delay1(1); P0=0X00; } } // 显示close 字符 void disp_close() { unsigned int i=400; while(i--) { P2=2; P0=0x39; //'C' delay1(1); P0=0X00; P2=3; P0=0x38; //'L' delay1(1); P0=0X00; P2=4; P0=0x3f; //'O' delay1(1); P0=0X00; P2=5; P0=0x6d; //'S' delay1(1); P0=0X00; P2=6; P0=0x79; //'E' delay1(1); P0=0X00; } } /*---------------------------------------------------------------------------------------- 这是主函数部分 --------------------------------------------------------------------------------------*/ void main() { unsigned int TempH,TempL; unsigned char H, L ; jdq=0; init_timer(); init_ds1302(); UARTinit(); while(1) { if(flag_get) //定时读取当前温度 { temp=ReadTemperature(); //这个函数8ms if(temp&0x8000) { temp=~temp; // 取反加1 temp +=1; } TempH=temp>>4; TempL=temp&0x0F; TempL=TempL*6/10;//小数近似处理 H=(unsigned char)TempH; L=(unsigned char)TempL; /**/ send_char_com('a'); send_char_com(H); send_char_com(L); send_char_com('e'); flag_get=0; } //这个循环用11ms if(control) { jdq=~jdq; if(jdq) { send_char_com('o'); send_char_com('e'); disp_open(); } else { send_char_com('c'); send_char_com('e'); disp_close(); } control=0; } if(set_time) { if((time[1]<0x60)||(time[2]<0x60)&&(time[3]<0x24)) { set_ds1302(time[1],time[2],time[3]); // s , m ,h //不知为何时间定时器自动停止. ,数组越界 set_time=0; } } if(!key_led) { control=1; } //添加时钟显示代码 get_ds1302(); //2.23ms } //不进第一个if 时间为 2ms 进入 13ms 这里指周期 } /******************************************************************/ /* 定时器中断 */ /******************************************************************/ void tim(void) interrupt 1 using 1//中断用于温度检测 { TR0=0; //关闭定时器 TH0=0x0f;//定时器重装值 定时器有没有中断标志位??,未清零? TL0=0x00; flag_get=1;//标志位有效 } void UART_SER() interrupt 4 { unsigned char Temp; static unsigned char flag=0; if(RI) { RI=0; Temp=SBUF; switch(Temp) { case 's': control=1; break; case 't': //set_time=1; flag=buff_size; break; case 'w': TR0=1; break; default: break; } if(flag) { flag--; time[flag]=Temp; //全局变量 if(time[0]=='e') { time[0]=0x11; set_time=1; } } } }
18b20.c
#include "reg52.h" #include "18b20.h" /******************************************************************/ /* 定义端口 */ /******************************************************************/ sbit DQ=P1^3;//ds18b20 端口 unsigned int temp; unsigned char flag_get=0 ; /******************************************************************/ /* 延时函数 */ /******************************************************************/ void delay(unsigned int i)//延时函数 { while(i--); } /******************************************************************/ /* 初始化 */ /******************************************************************/ void Init_DS18B20(void) { unsigned char x=0; DQ = 1; //DQ复位 delay(8); //稍做延时 DQ = 0; //单片机将DQ拉低 delay(80); //精确延时 大于 480us DQ = 1; //拉高总线 delay(10); x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败 delay(5); } /******************************************************************/ /* 读一个字节 */ /******************************************************************/ unsigned char ReadOneChar(void) { unsigned char i=0; unsigned char dat = 0; for (i=8;i>0;i--) { DQ = 0; // 给脉冲信号 dat>>=1; DQ = 1; // 给脉冲信号 if(DQ) dat|=0x80; delay(5); } return(dat); } /******************************************************************/ /* 写一个字节 */ /******************************************************************/ void WriteOneChar(unsigned char dat) { unsigned char i=0; for (i=8; i>0; i--) { DQ = 0; DQ = dat&0x01; delay(5); DQ = 1; dat>>=1; } delay(5); } /******************************************************************/ /* 读取温度 */ /******************************************************************/ unsigned int ReadTemperature(void) { unsigned char a=0; unsigned int b=0; unsigned int t=0; Init_DS18B20(); WriteOneChar(0xCC); // 跳过读序号列号的操作 WriteOneChar(0x44); // 启动温度转换 delay(200); Init_DS18B20(); WriteOneChar(0xCC); //跳过读序号列号的操作 WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度 a=ReadOneChar(); //低位 b=ReadOneChar(); //高位 b<<=8; t=a+b; return(t); }
ds1302.c
#include <reg52.h> #include "ds1302.h" //===以下IO定义请根据您硬件的连接修改=== sbit T_RST=P3^5;//ds1302-5 sbit T_IO=P3^4;//ds1302-6 sbit T_CLK=P3^6;//ds1302-7 sbit ACC0=ACC^0; sbit ACC7=ACC^7;//累加器A 51单片机原理中有介绍 unsigned char a,b,clock_ss,clock_sg,clock_fs,clock_fg,clock_ms,clock_mg; int hour,mie,sei; unsigned char clk_time[3]; //秒,分,时寄存器初始值 code unsigned char ledmap[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //数码管段码 /******************DS1302:写入操作(上升沿)*********************/ void write_byte(unsigned char da) { unsigned char i; ACC=da;//10000001 for(i=8;i>0;i--) { T_IO=ACC0; T_CLK=0; T_CLK=1; ACC=ACC>>1;//01000000 } } /******************DS1302:读取操作(下降沿)*****************/ unsigned char read_byte(void) { unsigned char i; for(i=0;i<8;i++)//00000001 假设ACC=00000000 { ACC=ACC>>1;//01000000 T_CLK = 1; T_CLK = 0; ACC7 = T_IO;//10000000 } return(ACC); } /******************DS1302:写入数据(先送地址,再写数据)***************************/ void write_1302(unsigned char addr,unsigned char da) { T_RST=0; //停止工作 T_CLK=0; T_RST=1; //重新工作 write_byte(addr); //写入地址 write_byte(da); T_RST=0; T_CLK=1; } /******************DS1302:读取数据(先送地址,再读数据)**************************/ unsigned char read_1302(unsigned char addr) { unsigned char temp; T_RST=0; //停止工作 T_CLK=0; T_RST=1; //重新工作 write_byte(addr); //写入地址 temp=read_byte(); T_RST=0; T_CLK=1; //停止工作 return(temp); } /***********************延时程序=a*1ms**************************************/ void delay1(unsigned char a) { unsigned int i; while(a-- !=0) { // led_disp(); for(i=0;i<12;i++); //12 } } /***********************显示程序**********************************************/ /* DS1302秒,分,时寄存器是BCD码形式: 用16求商和余进行"高4位"和"低4位"分离 */ /****************************************************************************/ void led_disp() { clock_ms=clk_time[0]/ 16; clock_mg=clk_time[0]%16; clock_fs=clk_time[1]/ 16; clock_fg=clk_time[1]%16; mie=clock_fs*10+ clock_fg; //这个有什么用? clock_ss=clk_time[2]/ 16; clock_sg=clk_time[2]%16;//BCD*to*10 hour=clock_ss*10+ clock_sg; //用16求商和余进行"高4位"和"低4位"分离 P2=0; P0=ledmap[clock_ss]; delay1(1); P0=0X00; P2=1; P0=ledmap[clock_sg];//时个位 delay1(1); P0=0X00; P2=2; P0=ledmap[10];//显示"-"数组里的 0x40 delay1(1); P0=0X00; P2=3; P0=ledmap[clock_fs];//分十位 delay1(1); P0=0X00; P2=4; P0=ledmap[clock_fg];//时个位 delay1(1);P0=0X00; P2=5; P0=ledmap[10];//显示"-"数组里的 0x40 delay1(1); P0=0X00; P2=6; P0=ledmap[clock_ms];//秒十位 delay1(1); P0=0X00; P2=7; P0=ledmap[clock_mg]; delay1(1); P0=0X00; } void init_ds1302() { write_1302(0x8e,0x80); //WP=1 写保护,加上这个操作之后断电重新上电是正确的时间. } void get_ds1302() { unsigned char temp=0x81; unsigned char i; for(i=0;i<3;i++)//分别把秒分时数据读出分3次读好一次地址加2" temp+=2;" { clk_time[i]=read_1302(temp); temp+=2; } led_disp(); } //添加设置时间的代码 ,结合key void set_ds1302(unsigned m,unsigned char f,unsigned char s) { write_1302(0x8e,0x00); //WP=0 写操作 /**/ write_1302(0x80,m);//0x80是写秒数据此处写进"01"秒 write_1302(0x82,f);//0x82是写分数据 write_1302(0x84,s);//0x84是写时数据 write_1302(0x8e,0x80); //WP=1 写保护 delay1(255); }
串口部分程序没有比较好写,我便不贴上来了.程序往上位机传输数据时,我这里没有考虑负数.所以如果需要使用本程序需要注意这一点.
这个是下位机程序开发日志:
已经实现串口控制台灯的开关. 下面添加串口测温功能 2013.11.22 目前系统有个奇怪的问题, 不能打开串口接收中断但是不发送 ,且发送不能少于2个byte . 当关闭ES 时不会出现这个问题 . 在初始化时 TI 置位会引用跳到串口接收中断部分 ,稍过后没有此问题. 每次发生 接收中断时系统运算减慢,过片刻正常. 2013.11.22 设置日期的格式 7423570965 't''h''m''s''e' 发送的数据 均为 0x00格式 比如说 设置为 20:00:01 则发送 't''0x20''0x00''0x01''e' 关于首次初始化问题 思路是将1302的某个寄存器定义为是否首次开机检测标志,比如存入0xaa数值。 上电时读取1302的这个寄存器,如果是0xaa,说明不是首次,便不再初始化,否则初始化,并向开机定义的寄存器中写入0xaa。 我这里直接对写保护位写 1. 2013.11.23 添加发送'w'获取温度 返回的数据 'a''H''L''e' 2013.11.24 添加返回台灯状态 'c''e' 'o''e' 添加握手信息 开机是请求获取一次温度 , 2013.11.24 添加 修改 second 2013.11.26 上述提到问题已经更正
上位机程序分析,程序界面如图:
上位机程序有几个我自认为的亮点. 1,可以联网校准电子时钟. 2,可以在右下角显示温度 . 3,可以在任何状态下按下快捷键控制台灯.这里主要讲解这三部分功能.我这里把打包好的程序共享给大家,有需要源码的可以在下面留言.
亮点功能1,联系校准电子时钟:
private void set_auto_Click(object sender, EventArgs e) { set_auto.Enabled = false; //关闭按键 set_time.Enabled = false; WebRequest wrt = null; WebResponse wrp = null; try { wrt = WebRequest.Create("http://www.time.ac.cn/timeflash.asp?user=flash"); wrt.Credentials = CredentialCache.DefaultCredentials; wrp = wrt.GetResponse(); StreamReader sr = new StreamReader(wrp.GetResponseStream(), Encoding.UTF8); string html = sr.ReadToEnd(); sr.Close(); wrp.Close(); int yearIndex = html.IndexOf("<year>") + 6; int monthIndex = html.IndexOf("<month>") + 7; int dayIndex = html.IndexOf("<day>") + 5; int hourIndex = html.IndexOf("<hour>") + 6; int miniteIndex = html.IndexOf("<minite>") + 8; int secondIndex = html.IndexOf("<second>") + 8; string year = html.Substring(yearIndex, html.IndexOf("</year>") - yearIndex); string month = html.Substring(monthIndex, html.IndexOf("</month>") - monthIndex); ; string day = html.Substring(dayIndex, html.IndexOf("</day>") - dayIndex); string hour = html.Substring(hourIndex, html.IndexOf("</hour>") - hourIndex); string minite = html.Substring(miniteIndex, html.IndexOf("</minite>") - miniteIndex); string second = html.Substring(secondIndex, html.IndexOf("</second>") - secondIndex); set_time_function(hour,minite,second); textBox1.Text = hour + ":" + minite + ":" + second; } catch (WebException web) { MessageBox.Show(web.Message); } catch (Exception xx) { MessageBox.Show(xx.Message); } finally { if (wrp != null) wrp.Close(); if (wrt != null) wrt.Abort(); } set_auto.Enabled = true; //打开按键 set_time.Enabled = true; }
这个功能代码我是参考下面[参考博客]部分的程序 ,实现了网络时间的获取,获取的格式为string 类型.这里如果想进行ds1302时间的设置,需要进行一下转码,方法如下:
/// <summary> /// 这里进行编码转化 ,ds1302 每一位是16进制数据.如果你想设置成12点, 需要发送 0x12 . /// </summary> /// <param name="code"></param> /// <returns></returns> private byte Transcoding(string code ) { byte[] bit = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49, 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59}; return bit[int.Parse(code)<60 ? int.Parse(code):59] ; }
亮点二,右下角动态显示温度
这个代码直接用的这个作者的http://www.codeproject.com/Articles/9361/WeatherNotify ,有兴趣的可以直接到这里查看.
亮点三,c# hook
代码参考第五条引用.原程序是有一点小错误,这里的更正方法如下:
在globalKeyboardHook.cs 文件中定义的委托下面添加这一句 private keyboardHookProc _keyboardHookProc; //新添加的
在 hook() 方法体中的代码更改为
/* IntPtr hInstance = LoadLibrary("User32"); hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0); */ //把引掉的部分更改为下面的 IntPtr hInstance = LoadLibrary("User32"); _keyboardHookProc = new keyboardHookProc(hookProc); hhook = SetWindowsHookEx(WH_KEYBOARD_LL, _keyboardHookProc, hInstance, 0);
如果想按下快捷键不对其它的程序产生影响,可以去掉这个方法体 public int hookProc(int code, int wParam, ref keyboardHookStruct lParam){}中的这一句
/*
if (kea.Handled)
return 1;
*/
好了,整个系统差不多介绍完了.虽然程序不太,但涉及到许多的知识 .需要上位机的源代码的可以留言.
博文为本人所写,转载请表明出处 电脑控制台灯
参考博客:
http://www.cnblogs.com/slyzly/articles/2108877.html
http://www.codeproject.com/Articles/9361/WeatherNotify
/article/5626604.html
http://bbs.csdn.net/topics/100169052
http://www.codeproject.com/Articles/19004/A-Simple-C-Global-Low-Level-Keyboard-Hook
相关文章推荐
- 控制DateTimePicker日期或时间的显示格式[C#]
- C#在一个控件上显示电脑当前的时间
- C# WinForm 控制DateTimePicker日期或时间的显示格式
- C# 获取人类可识别的文件大小转换显示 和 人类可识别的时间大小
- WPF c#后台代码控制样式显示
- sql语句控制时间的显示格式语句
- C# winform 串口通信时检测电脑可用串口并显示
- 使用Python控制1602液晶屏实时显示时间(附PyCharm远程调试)
- 注册时控制按钮上的时间显示
- C#文本框中,利用Timer实现时间实时显示
- asp.net 关于C#时间24进制显示问题
- timer控件控制显示系统时间,随时更新
- 使用javascript实现有效时间的控制,并显示将要过期的时间
- C#中使用DateTimePicker控件显示修改日期时间
- Toast源码分析 控制显示时间
- 使用C#模拟键盘输入、鼠标移动和点击、设置光标位置及控制应用程序的显示
- C#控制textbox中的输入数字固定显示2位小数
- 21.让你的电脑右下角的时间显示星期:
- 让你的电脑任务栏时间旁显示你爱的人的名字