Разработка программного обеспечения
⇐ ПредыдущаяСтр 2 из 2
Программа написана на языке СИ при этом, в качестве инструментальных средств была использована бесплатная программа AVR Studio 6 Принцип работы программы: в функции (init) производится настройка всех портов микроконтроллера, написание прерываний, инициализация таймеров, часов реального времени, индикатора и датчика влажности. Далее происходит старт таймера и обработка прерываний. Текст программы см. в приложении Г.
Результат компиляции и построения программы
Компиляция Построение начато. Проект "GMD.cproj" (целевые объекты Compile): Построение с инструментами версии "2.0". Целевой объект "Compile" в файле "C:\Program Files (x86)\Atmel\Atmel Studio 6.0\Vs\Compiler.targets" из проекта "C:\Users\Wackaloon\Desktop\Курсовик МПК\code\GMD.cproj" (точка входа): Задача "RunCompilerTask" C:\Program Files (x86)\Atmel\Atmel Studio 6.0\make\make.exe "GMD.o" make: `GMD.o' is up to date. Выполнение задачи "RunCompilerTask" завершено. Построение целевого объекта "Compile" в проекте "GMD.cproj" завершено. Построение проекта "GMD.cproj" завершено.
Build succeeded.
Построение AVR Memory Usage ---------------- Device: atmega8 Program: 4914 bytes (60.0% Full) (.text +.data +.bootloader) Data: 22 bytes (2.1% Full) (.data +.bss +.noinit) Done executing task "RunCompilerTask". Done building target "CoreBuild" in project "GMD.cproj". Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)'!= '') was evaluated as (''!= ''). Target "Build" in file "C:\Program Files (x86)\Atmel\Atmel Studio 6.0\Vs\Avr.common.targets" from project "C:\Users\Wackaloon\Desktop\Курсовик МПК\code\GMD.cproj" (entry point): Done building target "Build" in project "GMD.cproj". Done building project "GMD.cproj".
Build succeeded. ========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
1. DHT11 Temperature & humidity sensor, Datasheet – D Robotics UK 2. DHT22 Temperature & humidity module, Datasheet – AOSONG 3. DHT21 Digital-output temperature and humidity sensor, Datasheet – Hanwei
4. PC 0802-A, Datasheet – POWERTIP 5. PC 1002-A, Datasheet – POWERTIP 6. WH1602L, Datasheet – Winstar Display Co. LTD 7. DS1307 Real-time clock, Datasheet – Maxim Integrated 8. DS1390-1394 Real-time clock, Datasheet – Maxim Integrated 9. ATMega8(L), Datasheet – ATMEL 10. EG-BA -103, Datasheet – ener genie 11. К142ЕН5B, Спецификация [Электронный ресурс]: база данных. — Режим доступа: http://www.radiolibrary.ru/reference/chip/k142en5v.html. Дата обращения 25.03.14 12. L7805, Datasheet – STMicroelectronix 13. LM2596, Datasheet – Texas Instruments 14. Язык СИ для МК [Электронный ресурс]: база данных. — Режим доступа: http://www.123avr.com/05.htm. Дата обращения 2.04.14 15. ПРИЛОЖЕНИЕ А ПРИЛОЖЕНИЕ Б ПРИЛОЖЕНИЕ В ПРИЛОЖЕНИЕ Г
Текст программы
Файл timeout.h описывает частоту кварца #define F_CPU 16000000UL // 8 MHz #ifndef ALIBC_OLD #include <util/delay.h> #else #include <avr/delay.h> #endif
Файл dht22.h содержит объявления функций для работы с датчиком #ifndef _DHT22_H_ #define _DHT22_H_
#include <inttypes.h>
#define THERM_PIN PINC #define THERM_DDR DDRC #define THERM_PORT PORTC
#define THERM_DQ PC0 // датчик подключен на порт С 0 (ADC0) /* Utils */ #define THERM_INPUT_MODE() THERM_DDR&=~(1<<THERM_DQ) #define THERM_OUTPUT_MODE() THERM_DDR|=(1<<THERM_DQ) #define THERM_LOW() THERM_PORT&=~(1<<THERM_DQ) #define THERM_HIGH() THERM_PORT|=(1<<THERM_DQ) #define THERM_READ() ((THERM_PIN&(1<<THERM_DQ))? 1: 0)
typedef enum { DHT_ERROR_NONE = 0, DHT_BUS_HUNG, DHT_ERROR_NOT_PRESENT, DHT_ERROR_ACK_TOO_LONG, DHT_ERROR_SYNC_TIMEOUT, DHT_ERROR_DATA_TIMEOUT, DHT_ERROR_CHECKSUM, DHT_ERROR_TOOQUICK } DHT22_ERROR_t;
int dht22_read(float *temperature, float *humidity);
#endif /*_DHT22_H_*/
Файл dht22.cpp содержит определения функций для работы с датчиком, алгоритм взят из Datasheet
#include "DHT22.h" #include "../timeout.h" #include <avr/io.h> // здесь должно быть 40, но датчик добавляет еще один бит в начале #define DHT22_DATA_BIT_COUNT 41 // прочитать 40 бит данных с датчика, //сохранить результаты в приватной переменной чтобы прочитать паблик функциями int dht22_read(float *temperature, float *humidity) { uint8_t retryCount; uint8_t bitTimes[DHT22_DATA_BIT_COUNT]; int currentHumidity; int currentTemperature; uint8_t checkSum, csPart1, csPart2, csPart3, csPart4;
int i;
currentHumidity = 0; currentTemperature = 0; checkSum = 0;
// for(i = 0; i < DHT22_DATA_BIT_COUNT; i++)
{ bitTimes[i] = 0; }
// ждать пока не появится высокий уровень //cli(); THERM_INPUT_MODE(); //sei(); retryCount = 0; do { if (retryCount > 125) { return DHT_BUS_HUNG; } retryCount++; _delay_us(2); } while(!THERM_READ()); // послать активирующий запрос //cli(); THERM_LOW(); THERM_OUTPUT_MODE(); // низкий уровень на выходе //sei(); _delay_us(1100); // 1.1 ms //cli(); THERM_INPUT_MODE(); // переключиться обратно на вход //sei(); //найти начало импульса retryCount = 0; do { if (retryCount > 25) //(Spec is 20 to 40 us, 25*2 == 50 us) { return DHT_ERROR_NOT_PRESENT; } retryCount++; _delay_us(2); } while(!THERM_READ()); // найти конец импульса retryCount = 0; do { if (retryCount > 50) //(минимум 80 us, 50*2 == 100 us) { return DHT_ERROR_ACK_TOO_LONG; } retryCount++; _delay_us(2); } while(THERM_READ()); // прочитать 40 бит данных for(i = 0; i < DHT22_DATA_BIT_COUNT; i++) { // найти начало синхроимпульса retryCount = 0; do { if (retryCount > 35) //(минимум 50 us, 35*2 == 70 us) { return DHT_ERROR_SYNC_TIMEOUT; } retryCount++; _delay_us(2); } while(!THERM_READ()); // измерить размер импульса данных retryCount = 0; do { if (retryCount > 50) //(минимум 80 us, 50*2 == 100 us) { return DHT_ERROR_DATA_TIMEOUT; } retryCount++; _delay_us(2); } while(THERM_READ()); bitTimes[i] = retryCount; } // поиск конца каждого кусочка // 0 is 26 to 28 us // 1 is 70 us // bitTimes[x] <= 11 is a 0 // bitTimes[x] > 11 is a 1 // for(i = 0; i < 16; i++) { if(bitTimes[i + 1] > 11) { currentHumidity |= (1 << (15 - i)); } } for(i = 0; i < 16; i++) { if(bitTimes[i + 17] > 11) { currentTemperature |= (1 << (15 - i)); } } for(i = 0; i < 8; i++) { if(bitTimes[i + 33] > 11) { checkSum |= (1 << (7 - i)); } }
*humidity = ((float)(currentHumidity & 0x7FFF)) / 10.0;
if(currentTemperature & 0x8000) { // ниже нуля, не очень стандартно currentTemperature &= 0x7FFF; *temperature = ((float)currentTemperature / 10.0) * -1.0; } else { *temperature = (float)currentTemperature / 10.0; }
csPart1 = currentHumidity >> 8; csPart2 = currentHumidity & 0xFF; csPart3 = currentTemperature >> 8; csPart4 = currentTemperature & 0xFF;
if(checkSum == ((csPart1 + csPart2 + csPart3 + csPart4) & 0xFF)) { //*humidity = 10; return DHT_ERROR_NONE; } //*humidity = 20; return DHT_ERROR_CHECKSUM; }
Для работы с индикатором использовалась свободно распространяемая библиотека, автор Radu Motisan
Файл hd44780.h
/* @project * * License to access, copy or distribute this file: * This file or any portions of it, is Copyright (C) 2012, Radu Motisan, http://www.pocketmagic.net. All rights reserved. * This file can be used for free only in private use, educational and non commercial applications, assuming this original * copyright message is preserved. * * @ author Radu Motisan, radu.motisan@gmail.com * * This file is protected by copyright law and international treaties. Unauthorized access, reproduction * or distribution of this file or any portions of it may result in severe civil and criminal penalties. * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * @purpose HD44780 LCD Minimal interface for Atmega microcontrollers * http://www.pocketmagic.net/ */
#pragma once #include <stdio.h> #include <avr/io.h> //--------------------------------CONFIGURE LCD------------------------------------------------------// #define LCD_LINES 2 // number of visible lines of the display #define LCD_DISP_LENGTH 8 // visibles characters per line of the display #define LCD_START_LINE1 0x00 // DDRAM address of first char of line 1 #define LCD_START_LINE2 0x40 // DDRAM address of first char of line 2 #define LCD_START_LINE3 0x14 // DDRAM address of first char of line 3 #define LCD_START_LINE4 0x54 // DDRAM address of first char of line 4
//Purpose: work with a LCD display #define LCD_4BIT_D4_PORT PORTD // port for 4bit data bit 0 //D4 poz:3 connector...[digits 0,1,...] #define LCD_4BIT_D4_PIN 4 // pin for 4bit data bit 0 #define LCD_4BIT_D5_PORT PORTD // port for 4bit data bit 1 //D5 #define LCD_4BIT_D5_PIN 5 // pin for 4bit data bit 1 #define LCD_4BIT_D6_PORT PORTD // port for 4bit data bit 2 //D6 #define LCD_4BIT_D6_PIN 6 // pin for 4bit data bit 2 #define LCD_4BIT_D7_PORT PORTD // port for 4bit data bit 3 //D7 #define LCD_4BIT_D7_PIN 7 // pin for 4bit data bit 3 #define LCD_RS_PORT PORTC // port for RS line //D3 poz:1 connector #define LCD_RS_PIN 1 // pin for RS line #define LCD_E_PORT PORTC // port for Enable line //D4 poz:2 connector #define LCD_E_PIN 2 // pin for Enable line //#define LCD_RW_PORT LCD_PORT // port for RW line UNUSED - we only WRITE //#define LCD_RW_PIN 5 // pin for RW line UNUSED - we only WRITE //---------------------------------------------------------------------------------------------------//
// instruction register bit positions, see HD44780U data sheet #define LCD_CLR 0x0 // DB0: clear display #define LCD_HOME 0x1 // DB1: return to home position #define LCD_ENTRY_MODE 0x2 // DB2: set entry mode #define LCD_ENTRY_INC 0x1 // DB1: 1=increment, 0=decrement #define LCD_ENTRY_SHIFT 0x0 // DB2: 1=display shift on #define LCD_ON 0x3 // DB3: turn lcd/cursor on #define LCD_ON_DISPLAY 0x2 // DB2: turn display on #define LCD_ON_CURSOR 0x1 // DB1: turn cursor on #define LCD_ON_BLINK 0x0 // DB0: blinking cursor? #define LCD_MOVE 0x4 // DB4: move cursor/display #define LCD_MOVE_DISP 0x3 // DB3: move display (0-> cursor)? #define LCD_MOVE_RIGHT 0x2 // DB2: move right (0-> left)? #define LCD_FUNCTION 0x5 // DB5: function set #define LCD_FUNCTION_8BIT 0x4 // DB4: set 8BIT mode (0->4BIT mode) #define LCD_FUNCTION_2LINES 0x3 // DB3: two lines (0->one line) #define LCD_FUNCTION_10DOTS 0x2 // DB2: 5x10 font (0->5x7 font) #define LCD_CGRAM 0x6 // DB6: set CG RAM address #define LCD_DDRAM 0x7 // DB7: set DD RAM address #define LCD_BUSY 0x7 // DB7: LCD is busy
// set entry mode: display shift on/off, dec/inc cursor move direction #define LCD_ENTRY_DEC 0x04 // display shift off, dec cursor move dir #define LCD_ENTRY_DEC_SHIFT 0x05 // display shift on, dec cursor move dir #define LCD_ENTRY_INC_ 0x06 // display shift off, inc cursor move dir #define LCD_ENTRY_INC_SHIFT 0x07 // display shift on, inc cursor move dir
// display on/off, cursor on/off, blinking char at cursor position #define LCD_DISP_OFF 0x08 // display off #define LCD_DISP_ON 0x0C // display on, cursor off #define LCD_DISP_ON_BLINK 0x0D // display on, cursor off, blink char #define LCD_DISP_ON_CURSOR 0x0E // display on, cursor on #define LCD_DISP_ON_CURSOR_BLINK 0x0F // display on, cursor on, blink char
// move cursor/shift display #define LCD_MOVE_CURSOR_LEFT 0x10 // move cursor left (decrement) #define LCD_MOVE_CURSOR_RIGHT 0x14 // move cursor right (increment) #define LCD_MOVE_DISP_LEFT 0x18 // shift display left #define LCD_MOVE_DISP_RIGHT 0x1C // shift display right
// function set: set interface data length and number of display lines #define LCD_FUNCTION_4BIT_1LINE 0x20 // 4-bit interface, single line, 5x7 dots #define LCD_FUNCTION_4BIT_2LINES 0x28 // 4-bit interface, dual line, 5x7 dots #define LCD_FUNCTION_8BIT_1LINE 0x30 // 8-bit interface, single line, 5x7 dots #define LCD_FUNCTION_8BIT_2LINES 0x38 // 8-bit interface, dual line, 5x7 dots
// #define LCD_MODE_DEFAULT ((1<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC)) // address of data direction register of port x #define LCD_DDR(x) (*(&x - 1))
extern int g_nCurrentLine;
inline void lcd_e_high() { LCD_E_PORT |= _BV(LCD_E_PIN); } inline void lcd_e_low() { LCD_E_PORT &= ~_BV(LCD_E_PIN); } inline void lcd_rs_high() { LCD_RS_PORT |= _BV(LCD_RS_PIN); } inline void lcd_rs_low() { LCD_RS_PORT &= ~_BV(LCD_RS_PIN); } // flush channel E void lcd_toggle_e(void); // PURPOSE: send a character or an instruction to the LCD void lcd_write(uint8_t data,uint8_t rs); // PURPOSE: send an instruction to the LCD void lcd_instr(uint8_t instr);
// PURPOSE: Initialize LCD to 4 bit I/O mode void lcd_init(); // PURPOSE: send a character to the LCD void lcd_char(uint8_t data); // PURPOSE: send a null terminated string to the LCD eg. char x[10]="hello!"; void lcd_string(char *text); void lcd_string_format(char *szFormat,...); // PURPOSE: Set cursor to specified position // Input: x horizontal position (0: left most position) // y vertical position (0: first line) void lcd_gotoxy(uint8_t x, uint8_t y); // PURPOSE: Move cursor on specified line void lcd_setline(uint8_t line); // PURPOSE: Clear display and set cursor to home position void lcd_clrscr(void); // FUNCTION: lcd_home // PURPOSE: Set cursor to home position void lcd_home(void);
Основной файл проекта содержащий логику работы системы Файл GMD.cpp #include <avr/io.h> #include <stdlib.h> #include <string.h> #include "timeout.h" // определеяет F_CPU #include <avr/interrupt.h> #include <util/delay.h> #include <avr/sleep.h> // датчик #include "sensors/dht22.h" // lcd #include "lcd/hd44780.h" //настройка внешнего прерывния INT0 void init(void) { //настраиваем на срабатывание INT0 по переднему фронту MCUCR |= (1<<ISC01)|(1<<ISC00); //разрешаем внешнее прерывание INT0 GICR |= (1<<INT0); //Настроить (разрешить) прерывание по переполнению счетного регистра TCNT0: TIMSK |= (0<<OCIE2)|(0<<TOIE2)|(0<<TICIE1)|(0<<OCIE1A)|(0<<OCIE1B)|(0<<TOIE1)|(1<<TOIE0); //1 1 0 Счет от пина Т0. По ниспадающему фронту TCCR0 |= (1<<CS02)|(1<<CS01)|(0<<CS00); //отключаем АЦП ADCSRA |= (0<<ADEN); //отключаем аналоговый компаратор ACSR|= (1<<ACD); //отключаем watchdog WDTCR |= (1<<WDCE); WDTCR |= (0<<WDE); lcd_init(); lcd_clrscr(); TIMER0_OVF_vect(); sei(); sleep_cpu(); } //функция обработчик внешнего прерывания INT0 ISR(INT0_vect) { sleep_cpu(); } // обработчик переполнения счетчика ISR(TIMER0_OVF_vect) { cli(); sleep_disable();
lcd_home();
float t = 0, h = 0; dht22_read(&t,&h); lcd_gotoxy(0,0); lcd_string_format("Humidity"); lcd_gotoxy(0,1); lcd_string_format(" %2.2f", h);
// выбор режима сна set_sleep_mode(SLEEP_MODE_PWR_DOWN);
// в этом режиме МК может проснуться только от //внешнего прерывания по изменению уровня на INT0 INT1 или от сторожевого таймера //состояние регистров сохраняется (указано в даташите)
sleep_enable(); sei(); sleep_cpu();
// ZzZzZzZz..... } /* * основная программа */ int main(void) { while(1) {
} return (0); }
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|