×
单片机 > 单片机程序设计 > 详情

电脑控制台灯(c# hook,显示室温,联网校正时间)

发布时间:2020-06-06 发布时间:
|

突发奇想,于是便写了一个小程序用于控制台灯,这几天功能也在不断的完善中,目前基本已经完成.下面进行功能的简述的代码的分析.

整体设计包含下位机程序和上位机程序.下位机用的c语言,上位机用的c#

整个系统功能包括:定时采集室温在电脑右下角显示,可联网校准电子时钟,可以电脑端快捷键控制台灯.视频中展示的顺序为


1,自动获取温度,图标动态显示室温 2,手动获取温度 3,按钮控制台灯 4 ,快捷键控制台灯 5,联网校准电子时钟 6最后展示


在任何界面只要按下快捷键便可以打开台灯(windows hook).


下面进行整个系统代码和原理的介绍.


下位机,


硬件上 ,包括  51单片机,ds1302,18b20,uln2003,pl2303 .硬件连接图如下:

 下位机程序分析:


  1 /************************************************************************/

  2 //     本程序作者 HennSun ,转载请表明出处. 

  3 //

  4 /************************************************************************/

  5 #include

  6 #include "uart.h"

  7 #include "18b20.h"

  8 #include "ds1302.h"

  9 #define buff_size 5

 10 sbit jdq=P1^0;

 11 sbit key_led=P3^3;

 12 unsigned int num;

 13 unsigned char control=0,set_time=0;

 14 unsigned char time[buff_size];           //用于设定时间

 15 extern unsigned int temp;

 16 extern unsigned char flag_get;

 17 

 18 /*----------初始化定时器---------*/

 19 

 20 void init_timer()

 21 {

 22     TMOD =0x01;//定时器设置     T0工作于方式1 16位

 23     TH0=0xef;

 24     TL0=0xf0;

 25     ET0=1;       //定时器 0 中断允许 .

 26     TR0=1;        // run the timer0     这个中断会让单片机查询中断向量表.

 27     EA    = 1;                  //打开总中断

 28 }

 29 

 30 //显示 open 字符

 31 void disp_open()

 32 {

 33     unsigned int i=400;

 34     while(i--)

 35     {

 36         P2=2;

 37         P0=0x3f;  //'O'

 38         delay1(1);

 39         P0=0X00;

 40         

 41         P2=3;

 42         P0=0x73;  //'P'

 43         delay1(1);

 44         P0=0X00;

 45         

 46         P2=4;

 47         P0=0x79;   //'E'

 48         delay1(1);

 49         P0=0X00;

 50         

 51         P2=5;

 52         P0=0x37;   //'N'

 53         delay1(1);

 54         P0=0X00;

 55     }

 56 

 57 }

 58 // 显示close 字符

 59 void disp_close()

 60 {

 61     unsigned int i=400;

 62     while(i--)

 63     {

 64         P2=2;

 65         P0=0x39;  //'C'

 66         delay1(1);

 67         P0=0X00;

 68         

 69         P2=3;

 70         P0=0x38;  //'L'

 71         delay1(1);

 72         P0=0X00;

 73         

 74         P2=4;

 75         P0=0x3f;   //'O'

 76         delay1(1);

 77         P0=0X00;

 78         

 79         P2=5;

 80         P0=0x6d;   //'S'

 81         delay1(1);

 82         P0=0X00;

 83         

 84         P2=6;

 85         P0=0x79;   //'E'

 86         delay1(1);

 87         P0=0X00;

 88     }

 89     

 90 }

 91 

 92 

 93 /*----------------------------------------------------------------------------------------

 94                             这是主函数部分

 95 --------------------------------------------------------------------------------------*/

 96 void main()

 97 {

 98     unsigned int TempH,TempL;

 99     unsigned char H, L ;

100     jdq=0;

101     init_timer();

102     init_ds1302();

103     UARTinit();

104     

105     while(1)

106     {    

107         if(flag_get)       //定时读取当前温度

108         {

109             

110             temp=ReadTemperature();   //这个函数8ms

111             

112             if(temp&0x8000)

113             {

114                 temp=~temp;  // 取反加1

115                 temp +=1;

116             }

117             TempH=temp>>4;

118             TempL=temp&0x0F;

119             TempL=TempL*6/10;//小数近似处理

120             

121             H=(unsigned char)TempH;

122             L=(unsigned char)TempL;

123             /**/

124             send_char_com('a');

125             send_char_com(H);

126             send_char_com(L);

127             send_char_com('e');

128             flag_get=0; 

129             

130         }     //这个循环用11ms         

131         if(control)

132         {

133             jdq=~jdq;

134             if(jdq)

135             {

136                 send_char_com('o');

137                 send_char_com('e');

138                 disp_open();

139             }

140             else

141             {

142                 send_char_com('c');

143                 send_char_com('e');

144                 disp_close();

145             }

146             control=0;

147         }

148         if(set_time)

149         {

150             if((time[1]<0x60)||(time[2]<0x60)&&(time[3]<0x24))

151             {

152                 set_ds1302(time[1],time[2],time[3]);   // s , m ,h 

153                 //不知为何时间定时器自动停止.  ,数组越界

154                 set_time=0;

155             }

156         }

157         if(!key_led)

158         {

159             control=1;

160         }

161         //添加时钟显示代码

162         get_ds1302();  //2.23ms

163   }  //不进第一个if  时间为 2ms   进入 13ms  这里指周期

164 }

165 

166 /******************************************************************/

167 /*                  定时器中断                                    */

168 /******************************************************************/

169 void tim(void) interrupt 1 using 1//中断用于温度检测

170 {

171     TR0=0;       //关闭定时器

172     TH0=0x0f;//定时器重装值    定时器有没有中断标志位??,未清零?

173     TL0=0x00;

174     flag_get=1;//标志位有效

175 }

176 

177 

178 

179 

180 void UART_SER() interrupt 4   

181 {

182     unsigned char Temp;

183     static unsigned char flag=0;

184     if(RI)

185     {

186         RI=0;

187         Temp=SBUF;

188         switch(Temp)

189         {

190             case 's':    

191                 control=1;

192                 break;

193             case 't':

194                 //set_time=1;

195                 flag=buff_size;

196                 break;

197             case 'w':

198                 TR0=1;

199                 break;

200             default:

201                 break;

202         }

203         if(flag)

204         {        

205             flag--;

206             time[flag]=Temp;   //全局变量

207             if(time[0]=='e')

208             {

209                 time[0]=0x11;

210                 set_time=1;

211             }

212         }

213     }

214 

215 }


18b20.c


 1 #include "reg52.h"

 2 #include "18b20.h"

 3 /******************************************************************/

 4 /*                    定义端口                                    */

 5 /******************************************************************/

 6 sbit DQ=P1^3;//ds18b20 端口

 7 unsigned int temp;

 8 unsigned char flag_get=0 ;

 9 

10 

11 /******************************************************************/

12 /*                    延时函数                                    */

13 /******************************************************************/

14 void delay(unsigned int i)//延时函数

15 {

16  while(i--);

17 }

18 

19 /******************************************************************/

20 /*                    初始化                                      */

21 /******************************************************************/

22 void Init_DS18B20(void)

23 {

24  unsigned char x=0;

25  DQ = 1;    //DQ复位

26  delay(8);  //稍做延时

27  DQ = 0;    //单片机将DQ拉低

28  delay(80); //精确延时 大于 480us

29  DQ = 1;    //拉高总线

30  delay(10);

31  x=DQ;      //稍做延时后 如果x=0则初始化成功 x=1则初始化失败

32  delay(5);

33 }

34 

35 /******************************************************************/

36 /*                    读一个字节                                  */

37 /******************************************************************/

38 unsigned char ReadOneChar(void)

39 {

40 unsigned char i=0;

41 unsigned char dat = 0;

42 for (i=8;i>0;i--)

43  {

44   DQ = 0; // 给脉冲信号

45   dat>>=1;

46   DQ = 1; // 给脉冲信号

47   if(DQ)

48    dat|=0x80;

49   delay(5);

50  }

51  return(dat);

52 }

53 

54 

55 /******************************************************************/

56 /*                 写一个字节                                     */

57 /******************************************************************/

58 void WriteOneChar(unsigned char dat)

59 {

60  unsigned char i=0;

61  for (i=8; i>0; i--)

62  {

63   DQ = 0;

64   DQ = dat&0x01;

65   delay(5);

66   DQ = 1;

67   dat>>=1;

68  }

69 delay(5);

70 }

71 

72 

73 /******************************************************************/

74 /*                   读取温度                                     */

75 /******************************************************************/

76 unsigned int ReadTemperature(void)

77 {

78     unsigned char a=0;

79     unsigned int b=0;

80     unsigned int t=0;

81     Init_DS18B20();

82     WriteOneChar(0xCC); // 跳过读序号列号的操作

83     WriteOneChar(0x44); // 启动温度转换

84     delay(200);

85     Init_DS18B20();

86     WriteOneChar(0xCC); //跳过读序号列号的操作 

87     WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度

88     a=ReadOneChar();   //低位

89     b=ReadOneChar();   //高位

90 

91     b<<=8;

92     t=a+b;

93 

94     return(t);

95 }


ds1302.c


  1 #include

  2 #include "ds1302.h"

  3 

  4 //===以下IO定义请根据您硬件的连接修改===

  5 sbit T_RST=P3^5;//ds1302-5

  6 sbit T_IO=P3^4;//ds1302-6

  7 sbit T_CLK=P3^6;//ds1302-7

  8 sbit ACC0=ACC^0;

  9 sbit ACC7=ACC^7;//累加器A 51单片机原理中有介绍

 10 

 11 unsigned char a,b,clock_ss,clock_sg,clock_fs,clock_fg,clock_ms,clock_mg;

 12 

 13 int hour,mie,sei;

 14 

 15 unsigned char clk_time[3];  //秒,分,时寄存器初始值

 16 code unsigned char ledmap[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};

 17 //数码管段码                            

 18 

 19 /******************DS1302:写入操作(上升沿)*********************/ 

 20 void write_byte(unsigned char da)

 21 {

 22    unsigned char i;

 23    ACC=da;//10000001

 24    for(i=8;i>0;i--)

 25    { 

 26       T_IO=ACC0;

 27             T_CLK=0;     

 28       T_CLK=1;

 29       ACC=ACC>>1;//01000000

 30    }

 31 }

 32 /******************DS1302:读取操作(下降沿)*****************/

 33 unsigned char read_byte(void)

 34 {

 35    unsigned char i;

 36    for(i=0;i<8;i++)//00000001   假设ACC=00000000

 37    {

 38       ACC=ACC>>1;//01000000  

 39             T_CLK = 1;

 40             T_CLK = 0;

 41       ACC7 = T_IO;//10000000

 42    }

 43    return(ACC);

 44 

 45 }

 46 

 47 /******************DS1302:写入数据(先送地址,再写数据)***************************/ 

 48 void write_1302(unsigned char addr,unsigned char da)

 49 {

 50    T_RST=0;    //停止工作

 51    T_CLK=0;                                 

 52    T_RST=1;   //重新工作

 53    write_byte(addr);    //写入地址

 54    

 55    write_byte(da);

 56    T_RST=0;

 57    T_CLK=1;

 58 }

 59 

 60 /******************DS1302:读取数据(先送地址,再读数据)**************************/

 61 unsigned char read_1302(unsigned char addr)

 62 {

 63    unsigned char temp;

 64    T_RST=0;                                   //停止工作

 65    T_CLK=0;  

 66    T_RST=1;                         //重新工作

 67    write_byte(addr);   //写入地址

 68    temp=read_byte();

 69    T_RST=0;

 70    T_CLK=1;     //停止工作

 71    return(temp);

 72 }

 73 

 74 

 75 /***********************延时程序=a*1ms**************************************/

 76 void delay1(unsigned char a)

 77 {

 78    unsigned int i;

 79    while(a-- !=0)

 80    {    // led_disp();

 81         for(i=0;i<12;i++);  //12

 82    }

 83 }

 84 

 85 

 86 /***********************显示程序**********************************************/

 87 

 88 /* DS1302秒,分,时寄存器是BCD码形式:  用16求商和余进行"高4位"和"低4位"分离 */

 89 /****************************************************************************/           

 90 void led_disp()

 91 {   

 92         clock_ms=clk_time[0]/ 16;  

 93         clock_mg=clk_time[0]%16;

 94         

 95         clock_fs=clk_time[1]/ 16;  

 96         clock_fg=clk_time[1]%16;

 97         

 98         mie=clock_fs*10+ clock_fg;   //这个有什么用?

 99         

100         clock_ss=clk_time[2]/ 16;   

101         clock_sg=clk_time[2]%16;//BCD*to*10

102         hour=clock_ss*10+ clock_sg; //用16求商和余进行"高4位"和"低4位"分离

103     

104         P2=0;

105         P0=ledmap[clock_ss];

106         delay1(1);

107         P0=0X00;

108         P2=1;

109         P0=ledmap[clock_sg];//时个位

110         delay1(1);

111         P0=0X00;

112         P2=2;

113         P0=ledmap[10];//显示"-"数组里的 0x40

114         delay1(1);

115         P0=0X00;

116         P2=3;

117         P0=ledmap[clock_fs];//分十位

118         delay1(1);

119         P0=0X00;

120         P2=4;

121         P0=ledmap[clock_fg];//时个位

122         delay1(1);P0=0X00;   

123         P2=5;

124         P0=ledmap[10];//显示"-"数组里的 0x40

125         delay1(1);

126         P0=0X00;

127         P2=6;

128         P0=ledmap[clock_ms];//秒十位

129         delay1(1);

130         P0=0X00;

131         P2=7;

132         P0=ledmap[clock_mg];

133         delay1(1);

134         P0=0X00;                      

135 }

136 void init_ds1302()

137 {

138     write_1302(0x8e,0x80); //WP=1 写保护,加上这个操作之后断电重新上电是正确的时间.

139 }

140 void get_ds1302()

141 {

142   unsigned char temp=0x81; 

143      unsigned char i;

144     for(i=0;i<3;i++)//分别把秒分时数据读出分3次读好一次地址加2" temp+=2;"

145     {

146          clk_time[i]=read_1302(temp);

147          temp+=2;

148     }

149     led_disp();    

150 }

151 //添加设置时间的代码  ,结合key

152 void set_ds1302(unsigned m,unsigned char f,unsigned char s)

153 {

154     write_1302(0x8e,0x00); //WP=0 写操作

155     /**/

156     write_1302(0x80,m);//0x80是写秒数据此处写进"01"秒

157     write_1302(0x82,f);//0x82是写分数据

158     write_1302(0x84,s);//0x84是写时数据

159 

160     write_1302(0x8e,0x80); //WP=1 写保护  

161     delay1(255);

162 }


串口部分程序没有比较好写,我便不贴上来了.程序往上位机传输数据时,我这里没有考虑负数.所以如果需要使用本程序需要注意这一点.


这个是下位机程序开发日志:


已经实现串口控制台灯的开关.


下面添加串口测温功能


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("") + 6;

                int monthIndex = html.IndexOf("") + 7;

                int dayIndex = html.IndexOf("") + 5;

                int hourIndex = html.IndexOf("") + 6;

                int miniteIndex = html.IndexOf("") + 8;

                int secondIndex = html.IndexOf("") + 8;


                string year = html.Substring(yearIndex, html.IndexOf("") - yearIndex);

                string month = html.Substring(monthIndex, html.IndexOf("") - monthIndex); ;

                string day = html.Substring(dayIndex, html.IndexOf("") - dayIndex);

                string hour = html.Substring(hourIndex, html.IndexOf("") - hourIndex);

                string minite = html.Substring(miniteIndex, html.IndexOf("") - miniteIndex);

                string second = html.Substring(secondIndex, html.IndexOf("") - 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时间的设置,需要进行一下转码,方法如下:


 1 ///

 2         /// 这里进行编码转化 ,ds1302 每一位是16进制数据.如果你想设置成12点, 需要发送 0x12  .

 3         ///

 4         ///

 5         ///

 6         private byte Transcoding(string code )

 7         {

 8             byte[] bit = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,

 9                                     0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,

10                                     0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,

11                                     0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,

12                                     0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,

13                                     0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59};

14             return bit[int.Parse(code)<60 ? int.Parse(code):59] ;

15         }


亮点二,右下角动态显示温度


  这个代码直接用的这个作者的http://www.codeproject.com/Articles/9361/WeatherNotify   ,有兴趣的可以直接到这里查看.


亮点三,c# hook 


  代码参考第五条引用.原程序是有一点小错误,这里的更正方法如下:


  在globalKeyboardHook.cs  文件中定义的委托下面添加这一句   private keyboardHookProc _keyboardHookProc;    //新添加的


  在 hook() 方法体中的代码更改为



1 /*

2             IntPtr hInstance = LoadLibrary("User32");

3             hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);

4             */

5          //把引掉的部分更改为下面的

6             IntPtr hInstance = LoadLibrary("User32");

7             _keyboardHookProc = new keyboardHookProc(hookProc);

8             hhook = SetWindowsHookEx(WH_KEYBOARD_LL, _keyboardHookProc, hInstance, 0);


如果想按下快捷键不对其它的程序产生影响,可以去掉这个方法体 public int hookProc(int code, int wParam, ref keyboardHookStruct lParam){}中的这一句  


/*

if (kea.Handled) 

return 1;

*/



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
如何为单片机选择合适的负载电容