tag 标签: ATmega16

相关博文
  • 热度 21
    2014-7-25 20:40
    1166 次阅读|
    0 个评论
      摘 要: 当前人们对家居防火、防盗以及对家用电器远程控制的需求日益提升, 同时手机已经成为居民随身携带的通信工具, 基于此设计了一种基于GSM 模块的能够通过手机对家用电器进行远程控制的集火灾、入侵报警于一体的自动短信安防报警系统。该系统由AVR ATmega16 单片机外接GSM 模块作为控制主机, 由短信带密码操作, 可设定8 组用户电话号码, 可中文短信报警, 带有红外微波双鉴防盗和火灾检测无线通信接口, 有2 路无线控制继电器输出端, 可联动电源, 录像等工作。最后经实测表明系统具有很好的检测效果。   0   引言   随着我国大量现代化住宅小区的建成, 人们对住宅的防火、防盗以及对家用电器进行远程通断电的需求日益提升, 而在当前社会, 手机已经成为居民每日随身携带的通信工具, 基于此本文设计了一种基于GSM 模块的能够通过手机对家用电器进行远程通断电控制的集火灾、入侵报警于一体的可以自动向主人发送中文报警短信的安防报警系统。   1   系统结构   如图1 GSM 安防报警系统示意图所示, 本系统由AVR ATmeg a16 单片机外接GSM 模块作为控制主机,主机由短信带密码操作, 可设定8 组用户电话号码, 中文短信报警,系统具有3 路无线探测器( 红外微波防盗, 烟雾报警) 无线通信接口, 同时有2 路无线控制继电器输出端, 可联动电源, 录像等工作。3 路无线探测器分别由红外热释电传感器、微波传感器、烟雾传感器以及无线收发模块构成。红外热释电传感器和微波传感器共同构成微波红外复合入侵探测器,烟雾传感器主要用于火灾检测。一旦系统由主人通过手机短信打开后, 如果检测到有人非法入侵或者有火灾发生,该系统将在立刻发短信通知设定好用户号码的主人( 最多8 个手机号码) 。同时为了方便主人离家能够对家用电器等进行通断电的控制, 本系统还提供两路无线开关用作远程控制通断, 用户可通过短信命令对远程无线开关进行控制。 图1  GSM 安防报警系统示意图   如图2 系统主机结构图所示, 系统主机主要由MCU ( AT mega16 单片机) 、GSM( T C35i) 及电平转换模块、延时接口电路( 单稳态触发器) 及显示模块( 12865LCD ) 、315 MH z 发射电路、315 MHz 及433 MHz接收电路以及电源适配模块( AMS1117 3. 3和KIS3RR3 降压模块) 构成。 图2 系统主机结构图   1. 1   GSM 及电平转换模块   GSM 模块采用的是西门子工业级GSM 模块TC35i,由于T C35I UART 的电平为2. 9 V T TL电平, 不能直接与AT mega16 相连, 所以如图3 电平转换电路所示, 在RXD 端使用2 个简单的非门做电平转换以及在T XD 端串1 个限流电阻。由于TC35I 对电源要求较高( 电压下降超过400 mV 将复位) , 并且在发送数据期间电流峰值会达到2. 5 A, 所以在靠近T C35I的地方并联了3 300 uF 的大容量电解电容, 以减少对电源的要求。 图3   电平转换电路   1. 2   延时接口电路及显示模块   本系统接收外部的无线信号采用的是查询的方式,为了防止信号丢失, 并尽量和市面上相同编码的无线模块兼容, 本文设计了一个单稳态延时接口电路, 该电路的原理图如图4 所示, Q1 基极为高电平时, C2 保存的电量被释放, 比较器输出高点平, 当基极由高电平降为低电平时, C2 通过R3 充电, 比较器的反相端电位缓慢上升, 一旦C2 的电压高过V ref 则比较器翻转, 输出低电平, 从而达到延时的目的。 图4  单稳态触发器延时接口电路   显示部分由ST7920LCD 构成, LCD 与MCU 使用SPI 进行连接。当有按键按下时就触发LCD 背光。无线接口部分由于防盗报警, 烟雾报警, 以及短信远程控制同时被触发的概率很小, 故整个系统不必使用过多频点进行通信, 主机使用315 MHz 的无线模块对无线开关进行控制, 而热释电红外和微波位移传感器分别使用315 MHz, 433 MHz 两个不同频率对主机发送报警信号, 这样可以使得报警时互不干扰。烟雾传感器使用315 MHz 的频率对主机发送信号。     1. 3   主机无线收发模块   无线收发模块主要由无线编码芯片SC2262、无线解码芯片PT2272、315 MHz 发射模块以及接收模块组成。主机对无线开关进行控制时使用无线编码芯片SC2262, 地址设置与接收部分PT2272 一致, 且震荡电阻应匹配, 当MCU 上电后或者主机收到远程控制的短信, MCU 先根据EEPROM 内保存的无线开关状态改变PD4~ PD7 电平, 然后MCU 将发送一个宽度为1 s的低电平脉冲至PT2262 的16 引脚( TE) , 使SC2262对于PD4 ~ PD7 的数据进行编码再从17 脚输出至315 MHz发射模块。   由于市面上有些探测传感器的无线发射模块触发时只发高电平“1” ,所以主机解码芯片不能用带锁存的PT 2272L4, 否则PT 2272L4 输出的数据永远都是高电平, 会一直产生误报, 因此为了更好的与市面产品兼容,本系统主机无线接收部分采用了非锁存的PT2272M4芯片分别与315 MH z 和433 MHz 的接收模块连接。   这样当有人入侵触发报警时, 两个报警器发出的信号不会因为处在同一频率上而互相干扰而导致解码错误, 避免了检测到有人入侵但主机无报警的情况。烟雾报警器接收部分和微波报警器使用同一个PT2272 M4 和接收模块。由于红外、微波、烟雾报警被触发时发射的信号是不连续且不同步的, 所以接收到信号将由3 路的单稳态触发器做3 s 的高电平, 提高MCU 采样判断的准确性。   2   系统软件流程   系统的软件流程图如图5 所示。 图5   软件流程图   3   系统测试   微波感应器、红外感应器贴墙安装, 安装高度在3~5 m。对红外传感器从3 个不同角度进行测试, 分别为正对、前方偏右30℃ 、前方偏右45℃ , 测出有效感应距离分别为图6 中A、B、C 所示。微波传感器从3 个不同角度进行测试, 分别为正对、前方偏右30℃ 、前方偏右135℃ , 测出有效感应距离分别为图7 中A 、B、C 所示。红外感应器的最大感应直线距离达7 m, 最佳使用距离为6 m, 感应角度90℃ 。微波感应器的最大感应直线距离达9 m, 近距离全向有效, 最佳使用距离为5 m。 图6 红外传感器感应距离测试示意图 图7  微波传感器距离感应测试示意图    4   结语   本文设计的自动短信安防报警系统采用了热释电红外、微波双感应器, 大大减少了误报、漏报, 提高了安防报警系统应用的可靠性。由AVR ATmeg a16 单片机外接GSM 模块作为控制主机, 只要在GSM 网络范围内, 无论用户身在何处, 都能远程报警; 由短信带密码操作, 增加了系统的安全性; 可设定8 组用户电话号码,可中文短信报警; 带有红外微波双鉴防盗无线通信接口, 提供远程无线开关功能, 有2 路无线控制继电器输出端, 可联动电源, 录像等工作。本文的设计使得安防产品的性能得到了提高, 同时降低了系统的成本。
  • 热度 20
    2014-4-4 14:42
    877 次阅读|
    1 个评论
      第一次接触液晶屏(320*240, RA8835),用的CPU是ATmega16. 只想显示最简单的字母和数字,却怎么也调不通 。。求大侠相助   #include #include #include   #define F_CPU 1000000 //内部晶振1M    #include   //------------------------------------------------------------------------------ //Parameter Defines #define dispoff     0x58  //显示关闭    后续参数1字节 #define dispon      0x59  //显示状态打开  后续参数1字节   #define hdotscr     0x5a  //点位移量设置  后续参数1字节 #define ovlay       0x5b  //显示合成设置  后续参数1字节 #define cgramadr    0x5c  //CGRAM首地址设置 后续参数2字节 #define csrform     0x5d  //光标形状设置  后续参数2字节   #define csrdirr     0x4c  //光标向右方向移动 后续参数:无 #define csrdirl     0x4d  //光标向左方向移动 后续参数:无 #define csrdiru     0x4e  //光标向上方向移动 后续参数:无 #define csrdird     0x4f  //光标向下方向移动 后续参数:无   #define csrw        0x46  //设置光标地址  后续参数2字节 #define csrr        0x47  //读出光标地址  后续参数2字节   #define mwrite      0x42  //显示数据写入  后续参数N字节 #define mread       0x43  //显示数据读取  后续参数N字节     /*--------------------------------------------------------------*/ //#define busy        0x40  //忙信号D6   0100 0000 #define AP          0x28  //一行所占显示存储单元的字节数   //------------------------------------------------------------------------------ //===== MCU Interface =====   #define lcd_bus PORTB                      //PORTB 数据口 //-------------------------------------- #define WR_H   PORTD |= (12)              //WR 为高 #define WR_L   PORTD = ~(12)           //WR 为低 #define RD_H   PORTD |= (13)              //RD 为高 #define RD_L   PORTD = ~(13)              // RD为低 #define CE_H   PORTD |= (14)              //CE  为高    片选  #define CE_L   PORTD = ~(14)               //CE  为低 #define A0_H   PORTD |= (16)              //A0  为高    命令数据选择 #define A0_L   PORTD = ~(16)              //A0  为低 #define RST_H  PORTD |= (17)               //RST 为高    复位  #define RST_L  PORTD = ~(17)               //RST   为低   #define nBUSY (P30x08)   void wr_cmd80(unsigned char cmdx);  ///写命令 void wr_dat1335(unsigned char datax); //写数据 void init1335();     //初始化1335函数 void Full1335(void);//全屏显示 void SetCursor1335(unsigned char lsb,unsigned char msb);//设置光标 void clear1335(void);//清屏 void lattice_1335(unsigned int pixelW,unsigned char pixelH,unsigned char dat1,unsigned char dat2);//指定范围内写入数据 void locate_xy1(unsigned char x, unsigned char y);          //定位光标 void show_char(unsigned char x, unsigned char y,  char *string);    //字符串显示        ////CPU初始化////// void CPUInit( void )                                                                                                  {     DDRB  = 0xff;    PORTB = 0x00;                                        //B口输出   0, D0~D7    DDRD |= (12)|(13)|(14)|(16)|(17);     PORTD |= (12)|(13)|(14)|(16)|(17);         //D口输出 ,1,PD2为/WR PD3为/RD PD4为CE PD6为A0 PD7为/RST }   /////  标准8080时序写命令//////////////   unsigned char rd_status(void) {    unsigned char datx;    A0_L;    WR_H;     RD_L;    datx = lcd_bus;    RD_H;    return datx; }   void wr_cmd80(unsigned char cmdx)               //写命令 {    CE_L;    A0_H;    RD_H;        //lcd_cmd = cmdx;     lcd_bus = cmdx;    WR_L;    WR_H;         CE_H; } ////////////写数据/////////////////// void wr_dat1335(unsigned char datax) {       CE_L;    while(rd_status()0x80);        //0x80???    A0_L;    RD_H;        //lcd_para = datax;     lcd_bus = datax;    WR_L;    WR_H;         CE_H; } ////////初始化1335/////////////////////////////////// void init1335() {    wr_cmd80(0x40);          //SYSTEM SET    wr_dat1335(0x30);       //p1    wr_dat1335(0x87);       //p2   FX    wr_dat1335(0x07);      //p3   FY    wr_dat1335(0x27);        //p4   C/R    27    wr_dat1335(0x42);      //p5    42   TC/R    wr_dat1335(0xEF);       //p6   L/F             ef    wr_dat1335(0x28);       //p7   APL    28    wr_dat1335(0x00);      //p8 APH    wr_cmd80(0x44);        //SCROLL    wr_dat1335(0x00);      //sa1-L    wr_dat1335(0x00);      //sa1-H    wr_dat1335(0xF0);       //sL1        wr_dat1335(0x00);      //sa2-L       wr_dat1335(0x28);     //sa2-H      wr_dat1335(0xF0);       //sL2      wr_dat1335(0x00);      //sa3-L      wr_dat1335(0x50);      //sa3-H      wr_dat1335(0x00);      //sa4-L    wr_dat1335(0x00);      //sa4-H             wr_cmd80(0x5a);       //HDOT SCR    wr_dat1335(0x00);              wr_cmd80(0x58);       //DISP OFF    wr_dat1335(0x54);                      wr_cmd80(0x5d);       //CSR FORM    wr_dat1335(0x00);      //CRX    wr_dat1335(0x00);      //CRY       wr_cmd80(0x59);       //DISP ON    wr_dat1335(0x54);            wr_cmd80(0x5b);           wr_dat1335(0x00);     }    //////////全屏////////////////////////// void Full1335(void) {        unsigned int i; wr_cmd80(0x5b);            wr_dat1335(0x00);      SetCursor1335(0x00,0x00);       wr_cmd80(0x42); for(i=0;i0x2580;i++)             wr_dat1335(0x1F);     for(;i0x7fff;i++)             wr_dat1335(0xFF); } ///////清屏///////////// void clear1335(void) {        unsigned int i; wr_cmd80(0x5b);            wr_dat1335(0x00);      SetCursor1335(0x00,0x00);      wr_cmd80(0x42); for(i=0;i0x2580;i++)             wr_dat1335(0x20);     for(;i0x7fff;i++)             wr_dat1335(0x00); } ///////设置光标////////// void SetCursor1335(unsigned char lsb,unsigned char msb) {     wr_cmd80(0x46);     //设置光标地址     wr_dat1335(lsb);     wr_dat1335(msb); wr_cmd80(0x42); }   ////////////指定范围内写入数据/////////////  void lattice_1335(unsigned int pixelW,unsigned char pixelH,unsigned char dat1,unsigned char dat2) { unsigned char i,k,tmp1,tmp2; tmp1 = pixelH/2; tmp2 = (unsigned char)(pixelW/8); SetCursor1335(0x80,0x25); for(k=0;k   {     for(i=0;i      wr_dat1335(dat1);       for(i=0;i      wr_dat1335(dat2);   } }   /*--------------------------------------------------------------*/ //光标定位 //x横坐标: 0~39 320/8=40 //y纵坐标: 0~29 240/8=30 void locate_xy1(unsigned char x, unsigned char y) {  unsigned int  addr;  addr  =(unsigned int)(y) * AP + x;  wr_cmd80(csrw);       //写入光标地址  wr_dat1335((unsigned char)(addr 0xff));  //先写低八位  wr_dat1335((unsigned char)(addr 8));  //后写高八位 }   /*--------------------------------------------------------------*/ //显示字符串 //x横坐标: 0~39 320/8=40 //y纵坐标: 0~29 240/8=30 void show_char(unsigned char x, unsigned char y,  char *string) {  locate_xy1(x, y);    //光标定位  wr_cmd80(csrform);    //光标形状设置  wr_dat1335(0x07);    //水平显示宽度6  wr_dat1335(0x07);    //线状光标显示,高度8    wr_cmd80(csrdirr);    //光标向右方向移动    wr_cmd80(dispon);    //显示状态开启  wr_dat1335(0x57);    //显示图像,光标1Hz闪烁    wr_cmd80(mwrite);    //显示数据写入  while(*string)   {   wr_dat1335(*string);    string++;  } }   //////////////主函数/////////////////// int main(void) {      _delay_ms(50);    CPUInit();                    //初始化CPU       _delay_ms(50);                                                                                                                  //CPU初始化    RST_L;                        //复位                                                                                                                            //RESET    _delay_ms(50);    RST_H;                            _delay_ms(50);          init1335();                   //初始化液晶屏       //RD_H; while(1)   {       Full1335();                    //全屏    _delay_ms(1000);         clear1335();                   //清屏  _delay_ms(1000);                                                                                                        /*lattice_1335(320,240,0x55,0xaa);                                      //指定范围内写入数据    _delay_ms(1000); lattice_1335(320,240,0xaa,0x55);        _delay_ms(1000); lattice_1335(320,240,0xff,0x00);        _delay_ms(1000);  lattice_1335(320,240,0x00,0xff);                                                                        _delay_ms(1000);  */         show_char(0, 0, "Hi");                        //显示字符串    };   }   ;i++) ;i++) ;k++)
  • 热度 16
    2012-9-24 08:55
    4095 次阅读|
    1 个评论
      笔记均为原创,欢迎转载,转载请注明出处!   笔记1:8种LED点亮模式_GCC.pdf 笔记2:有源蜂鸣器驱动实验_GCC.pdf 笔记3:按键扫描(用KEY选择对应LED点亮)_GCC.pdf 笔记4:按键扫描_8种LED亮灭模式控制_GCC.pdf 笔记5:按键扫描(增加防抖功能)_GCC.pdf 笔记6:无源蜂鸣器驱动实验_GCC.pdf 笔记7:外部中断INT0实验_GCC.pdf 笔记8:7种LED亮灭模式_INT0中断_蜂鸣器_GCC.pdf 笔记9:蜂鸣器产生音节节拍_GCC.pdf 笔记10:按键扫描(KEY控制对应LED亮灭)_GCC.pdf 笔记11:SPI实验(数码管显示)_GCC.pdf 笔记12:SPI实验(数码管位显示控制)_GCC.pdf 笔记13:SPI实验(数码管显示INT0次数)_GCC.pdf 笔记14:TC0产生PWM调节LED亮度_GCC.pdf 持续更新中,敬请关注......
  • 热度 18
    2012-7-3 17:48
    2233 次阅读|
    0 个评论
    关于DS18B20温度传感器的控制,在网络上也有很多的参考代码,但自己在查找的时候发现都不尽相同,甚至很多都无法通用。于是想自己整理一份可供大家参考的设计。 DS18B20概述: 如下图,是几种DS18B20的封装。传感器一共三个管脚,VDD、DQ、GND。 供电模式:共有两种供电模式——寄生电源模式和外部供电模式。寄生电源模式由DQ管脚供电,GND和VDD都接地;外部供电模式由VDD和GND供电,注意电源使用直流电+3-+5V。 配置电路:如下图DS18B20结构图,通信时需在DQ总线上接一个4.7k的上拉电阻用来释放总线。需注意的是,有时候采用的控制器,如单片机内部是带有上拉电阻的,此时不宜再在外部接上拉电阻。因为如果多接了上拉电阻后,相当于在原有上拉电阻并联了一个电阻,使得新的“上拉电阻”的阻值呈指数递减,会引起总线传输低电平时,电流增大,相应的低电平增大。 时序控制:单片机控制DQ单总线访问DS18B20时每个工作周期协议分三步。 1、初始化; 2、ROM操作(如果不操作,发送0xCC指令跳过ROM操作); 3、功能指令+返回参数;   初始化及读写字节时序如下图: 初始化时序: 首先我们必须对DS18B20芯片进行复位,复位就是由控制器(单片机)给DS18B20单总线至少480uS的低电平信号。当18B20接到此复位信号后则会在15~60uS后回发一个芯片的存在脉冲。存在脉冲:在复位电平结束之后,控制器应该将数据单总线拉高,以便于在15~60uS后接收存在脉冲,存在脉冲为一个60~240uS的低电平信号。至此,通信双方已经达成了基本的协议,接下来将会是控制器与18B20间的数据通信。如果复位低电平的时间不足或是单总线的电路断路都不会接到存在脉冲,在设计时要注意意外情况的处理。 读写时序: 写时间隙: 写时间隙分为写“0”和写“1”,时序如图。在写数据时间隙的前15uS总线需要是被控制器拉置低电平,而后则将是芯片对总线数据的采样时间,采样时间在15~60uS,采样时间内如果控制器将总线拉高则表示写“1”,如果控制器将总线拉低则表示写“0”。每一位的发送都应该有一个至少15uS的低电平起始位,随后的数据“0”或“1”应该在45uS内完成。整个位的发送时间应该保持在60~120uS,否则不能保证通信的正常。 读时间隙: 读时间隙时控制时的采样时间应该更加的精确才行,读时间隙时也是必须先由主机产生至少1uS的低电平,表示读时间的起始。随后在总线被释放后的15uS中DS18B20会发送内部数据位,这时控制如果发现总线为高电平表示读出“1”,如果总线为低电平则表示读出数据“0”。每一位的读取之前都由控制器加一个起始信号。注意:必须在读间隙开始的15uS内读取数据位才可以保证通信的正确。 在通信时是以8位“0”或“1”为一个字节,字节的读或写是从高位开始的,即A7到A0.字节的读写顺序也是自上而下的。   本程序设计只对 DS18B20 做两个操作:转换温度和读取温度,则两个工作周期如下:复位、跳过 ROM 指令 、执行温度转换存储器操作指令 、等待 750ms 温度转换时间;紧接着执行第二个周期:复位、跳过 ROM 指令 、执行读 RAM 的存储器操作指令 、读数据(最多为 9 个字节,中途可停止,只读简单温度值则读前 2 个字节即可)。代码如下: 以下是代码片段: //ATmega16晶振为8Mhz #include #include #define uchar unsigned char #define uint unsigned int #define F_CPU  8000000       #define BAUD   250000 //下面定义了新加的部分参数和函数 //DQ接在了PB2管脚上 #define DQ PB2 //风扇开启温度设置 #define TEMPERATURE 28 //风扇接开关接在了PA3管脚上 #define FAN PA3 //将风扇管脚置为输出 #define FAN_INI() DDRA|=BIT(FAN) //开风扇,即PA3输出高电平 //原理就是让RFD123的栅极和源级有个2到4V的开启电压 //这样漏极和源极就导通了,风扇就开了 #define FAN_ON() PORTA |= BIT(FAN) //关风扇,即PA3输出低电平 //栅极和源极电压小于2V,漏极和源极就断开 #define FAN_OFF() PORTA = ~BIT(FAN) //下面是DQ总线的操作 //总线拉高 #define SET_DQ() PORTB |= BIT(DQ) //总线清零 #define CLR_DQ() PORTB = ~BIT(DQ) //总线为输出 #define DQ_OUT() DDRB |= BIT(DQ) //总线为输入 #define DQ_IN() DDRB = ~BIT(DQ) /*--------------------DS18B20处理程序------------------*/ //延时1us void DELAY_1US() { NOP();   } //延时delay个us void DELAY_US(uint delay) { do {   delay--; } while(delay1);   } //延时delay个ms //这里中间插入了很多pwmbo1()这个函数 //因为在操作温度传感器的时候, //需要先进行温度转换,会有长时间的等待, //而这段时间里面,pwm波形需要正常运转, //所以每隔100us插入一个pwm控制,来保证灯的控制 void DELAY_MS(uint delay) { while(delay!=0) {   DELAY_US(1000);   delay--; }  } //DS18B20复位功能函数 void DS_RESET() { SET_DQ(); NOP(); NOP(); CLR_DQ(); DELAY_US(600); SET_DQ(); DQ_IN(); DELAY_US(30); if(PINBBIT(DQ)) {   DQ_RESET = 0; } else {   DQ_RESET = 1; } DELAY_US(300); DQ_OUT(); SET_DQ(); } //DS18B20写字节函数 void DS_WRITE(uchar DATA) { uchar i; for(i=0;i8;i++) {   DQ_OUT();   SET_DQ();   NOP();   NOP();   CLR_DQ();   DELAY_US(15);   if(DATA 0X01)    SET_DQ();   DELAY_US(60);   SET_DQ();   DATA=1;      } } //DS18B20读字节函数 uchar DS_READ() { uchar i,data_read; data_read = 0; DQ_OUT(); for(i=0;i8;i++) {   CLR_DQ();   DELAY_US(1);   SET_DQ();   NOP();   DQ_IN();   NOP();   DELAY_US(5);   if(PINBBIT(DQ))    data_read |= BIT(i);   else    data_read = ~BIT(i);   DELAY_US(70);   DQ_OUT();   NOP();   SET_DQ();    } return data_read; } //读温度函数,返回截取之后的温度值 uchar READ_TEMPERATURE() { //设置几个变量来保存读取的值和温度值 uchar TEMP1,TEMP2,TEMP; TEMP1 = 0; TEMP2 = 0; TEMP = 0; //第一个工作周期 //先复位 DS_RESET(); //写CCH,跳过ROM操作 DS_WRITE(0XCC); //写44H,温度转换命令 DS_WRITE(0X44); //下面是等待DS18B20转换温度 //先插入一个PWM控制 pwmbo1(); //等待750ms,其中也要插入PWM控制 DELAY_MS(750); //第二个工作周期 //先复位 DS_RESET(); //写CCH,跳过ROM操作 DS_WRITE(0XCC); //写BEH,进行读取寄存器 DS_WRITE(0XBE); //读寄存器第一个值,温度表示的低字节 TEMP1 = DS_READ(); //读寄存器第二个值,温度表示的高字节 TEMP2 = DS_READ(); //温度转换,取低字节的高4位做温度低4位 //取高字节的低4位做温度的高4位 TEMP = ((TEMP20X0F)4)|((TEMP10XF0)4); //返回温度值 return TEMP;   } void main(void) {  int ad,value; //PORTA输出为低 //PA3为风扇开关,风扇初始关闭 PORTA=0X00; DDRA=0XFF; //PORTB设置输出,并输出高,PB2为温度传感器的通信口 //设置为高,总线闲置 PORTB=0XFF; DDRB = 0XFF; while(1) { //下面是读取温度函数   TEMPE = READ_TEMPERATURE(); //如果读取的温度大于某个值,开启风扇, //小于了某个值关闭风扇 //这两个值可以实际测测,现在是28℃ //个人建议可以把关闭的值设定的比开启的值更低, //这样风扇不会开关得那么快 //TEMPERATURE的设置在预编译里面定义了,最上面   if(TEMPE TEMPERATURE)    FAN_ON();   else if(TEMPE (TEMPERATURE-3))    FAN_OFF(); } } 用示波器读取到温度 ( 00110001 10000000 ) 019BH=25.75 ℃,如下图:      
  • 热度 30
    2012-4-23 00:02
    12645 次阅读|
    17 个评论
              相信大家都用过STC系列的51单片机,STC系列的单片机烧录程序都很简单,只需要通过串口就可以实现程序的烧录。于是就想让avr的芯片也能实现通过串口就能下载的功能,这样就可以省去购买usbasp下载线或者高压编程器的费用了。仔细研究avr的芯片手册,发现都是带有bootloader功能,同时这个bootloader功能可以读写芯片的整个flash存储区,并且包括bootloader区,而且还有另外一个特点:如果bootloader功能开启以后,每次复位都会从bootloader启动。                 接下来再来研究一下STC芯片的烧录功能:当在烧录软件中按下“下载”按钮以后,烧录软件会通过传给给STC芯片不停的发送一串数据,此时给STC芯片下电,然后上电,芯片上电以后,首先检测是否有烧录的请求,如果有就开始烧录程序,如果没有就开始执行芯片flash中的程序。          于是就有一个大概的思路了,可以给avr的芯片写一个bootloader的串口通信的程序,首先检测是否有烧录请求,如果有就更新flash中的程序,如果没有烧录请求,则执行flash中原有的程序。经过几天的努力这个通过串口给atmega16烧录程序的固件和上位机终于完成了,为了方便大家这里共享处原理图和固件程序。其实这种功能应该有人已经实现了,至少国外的开源硬件arduino就是通过这种方式给atmega8烧录程序的,但是atmega16我没有找到现成的,于是就自己实现了一个。          烧录软件使用winavr中的avrdude程序。这也是一个开源项目,avrdude是一个控制台程序,操作不是很方便,于是写了一个应用程序封装了一下。   原理图:         原理图实际上就是一个带有串口的avr最小系统。     烧录bootloader程序:          下载 ATMega16串口下载.rar 安装包,解压到本地目录,使用usbasp把“bootloader" 文件夹下的固件烧录到atmega16里,然后修改熔丝位:       验证烧录程序:           把自制的板子通过串口和电脑相连,运行 “AvrSelfProgram.exe” 程序:           在软件中选择正确的串口,并浏览打开要烧录的hex固件,此时按下板子上的复位按钮,然后点击“写FLASH”按钮。这里需要注意:由于芯片复位以后等待烧录请求,如果3秒内没有请求则开始运行上次烧录的程序,所以在板子复位以后,要在3秒之内点击“写FLASH”按钮才能烧录成功,否则就会失败,最开始这个时间可能不好把握,可以多试几次掌握节奏。 如果看到下边的提示,说明程序已经烧录成功:     添加Win7版本的支持,具体请下载附件中Win7软件包。
相关资源