Форум закрыт для публикаций и работает только для чтения.
Отзывы о работе магазина и товарах просим оставлять на сайте интернет-магазина https://ekits.ru

AVR для начинающих.

Обсуждение вопросов программирования контроллеров AVR

Модераторы: Alexl81, Vitalii

Alexl81
Сообщения: 997
Зарегистрирован: 10 окт 2010, 11:09
Откуда: Россия, Челябинская область.
Контактная информация:

Re: AVR для начинающих.

Сообщение Alexl81 » 01 дек 2014, 12:52

Здравствуйте. Приобрёл ультразвуковой сенсор HC-SR04, ниже приведен код программы для работы с сенсором. Вывод Trig - к выводу PORTD.4 (порт-D бит-4), Echo - к выводу PORTD.2 - данный порт настраиваем на внешнее прерывание, на любое изменение сигнала(фронт, спад). Также приведены фото датчика, и работа в сборе.

/*****************************************************
Project : HC-SR04_ultrozvuk
Version : 1
Chip type : ATmega8
Program type : Application
AVR Core Clock frequency: 8,000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
*****************************************************/


#include <mega8.h>
#include <alcd.h>
#include <delay.h>

unsigned int timer_1,timer0_ovf,distance=0,overflow=0;
unsigned long duration=0;

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
if (PIND.2==1) { // если на входе высокий уровень (лог 1)
TCCR0=0x01; } // запускаем таймер 0

else { // если низкий (лог 0)
TCCR0=0x00; // останавливаем таймер 0
duration = (TCNT0+(timer0_ovf<<8)); // считаем количество импульсов
duration = (duration*0.125); // переводим в микросекунды
TCNT0 = 0; // сбрасываем счетчик таймера 0
timer0_ovf = 0; // сбрасываем счетчик переполнения
distance = (duration*0.1725); // переводим в миллиметры
TCCR1B=0x02; }; // запускаем таймер 1, повторяя цикл измерения

}

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
timer0_ovf++; // счетчик переполнения
if (timer0_ovf==255) { // если счетчик заполнялся
overflow=1; // устанавливаем флаг переполнения
TCCR0=0x00; // останавливаем таймер 0
TCNT0 = 0; // сбрасываем счетчик таймера 0
timer0_ovf = 0; // сбрасываем счетчик переполнения
TCCR1B=0x02; }; // запускаем таймер 1, повторяя цикл измерения
}

// Timer1 overflow interrupt service routine 10 мс
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{

TCNT1H=0xD8F0 >> 8;
TCNT1L=0xD8F0 & 0xff;
timer_1++;
if (timer_1>=60) {
// таймер 60 мс
TCCR1B=0x00; // отключаем таймер 1
TCNT1H=0xD8; // устанавливаем счетчик таймера 1 в исходное состояние
TCNT1L=0xF0; // устанавливаем счетчик таймера 1 в исходное состояние
timer0_ovf = 0; // обнуляем переполнения таймера 0
TCNT0=0x00; // обнуляем счетчик таймера 0
PORTD.4=1; // на порт D.4 устанавливаем лог 1
delay_us(10); // задержка в 10 мкс
PORTD.4=0; // порт D.4 сбрасываем в 0
};
}



void main(void)
{

PORTD=0x00;
DDRD=0x10;

TCCR0=0x00;
TCNT0=0x00;

TCCR1A=0x00;
TCCR1B=0x02;
TCNT1H=0xD8;
TCNT1L=0xF0;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

GICR|=0x40;
MCUCR=0x01;
GIFR=0x40;

TIMSK=0x05;

lcd_init(16);

// Global enable interrupts
#asm("sei")

while (1)
{

lcd_gotoxy(0,0);
lcd_putchar(distance/1000+0x30);
lcd_putchar((distance%1000)/100+0x30);
lcd_putchar((distance%100)/10+0x30);
lcd_putchar(distance%10+0x30);
lcd_putsf(" mm");

}
}

DSC_0582.JPG
Сенсор
DSC_0574.JPG
Конструкция в сборе

Alexl81
Сообщения: 997
Зарегистрирован: 10 окт 2010, 11:09
Откуда: Россия, Челябинская область.
Контактная информация:

Re: AVR для начинающих.

Сообщение Alexl81 » 01 дек 2014, 13:32

Здравствуйте. Приобрёл барометр BMP085, ниже приведен код программы для работы с барометром. Барометр работает по шине I2C, вот только напряжения питания у него 3,3В, соответственно если МК работает от 5В, то на прямую его нельзя включать. Я использовал конвертер сигналов как описано тут. Также приведены фото датчика, и работа в сборе.

/*****************************************************
Project : BMP085_I2C_Nokia5110
Version : 2
Date : 26.11.2014
Chip type : ATmega328P
Program type : Application
AVR Core Clock frequency: 8,000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 512
*****************************************************/


#include <mega328p.h>
#include <i2c.h>
#include <glcd.h>
#include <font5x7.h>
#include <delay.h>

#define BMP085_W 0xEF // запись - Write address
#define BMP085_R 0xEE // чтение - Read address
#define OSS 3

unsigned char timer_1,summa=0;
int AC1,AC2,AC3,B1,B2,MB,MC,MD;
unsigned int AC4,AC5,AC6,pressur,timer_2;
signed int temperatur;
signed long temperatur_1;
unsigned long pressur_1,pres_temp,pres_temp_1;

/************ Чтение из BMP085 2 байта **************/
long BMP_read_2_bytes(unsigned char address) {
unsigned char msb=0,lsb=0; // 8 битные переменные для чтения данных
long data; // 32 битная переменная для суммирования
delay_ms(5); // пауза 10 мс
i2c_start(); // посылаем команду "старт" в шину i2c
i2c_write(BMP085_R); // посылаем в шину адрес устройства
i2c_write(address); // посылаем в шину адрес читаемой ячейки
i2c_start(); // снова посылаем "старт" в шину
i2c_write(BMP085_W); // перевод в режим чтения
msb=i2c_read(0); // принимаем данные с лини и сохраняем в переменную
i2c_stop(); // посылаем команду "стоп"

delay_ms(5); // пауза 10 мс
i2c_start(); // посылаем команду "старт" в шину i2c
i2c_write(BMP085_R); // посылаем в шину адрес устройства
i2c_write(address+1); // посылаем в шину адрес читаемой ячейки
i2c_start(); // снова посылаем "старт" в шину
i2c_write(BMP085_W); // перевод в режим чтения
lsb=i2c_read(0); // принимаем данные с лини и сохраняем в переменную
i2c_stop(); // посылаем команду "стоп"

delay_ms(5); // пауза 10 мс
data = msb; // к перемененной data присваиваем значение msb
data<<= 8; // сдвигаем на 8 бит влево
data|=lsb; // прибавляем ещё значение lsb
return data; // возвращаем значение прочитанного
}

/************ Чтение из BMP085 3 байта **************/
long BMP_read_3_bytes(unsigned char address) {
unsigned char msb=0,lsb=0,xlsb=0; // 8 битные переменные для чтения данных
long int data; // 32 битная переменная для суммирования
delay_ms(5); // пауза 10 мс
i2c_start(); // посылаем команду "старт" в шину i2c
i2c_write(BMP085_R); // посылаем в шину адрес устройства
i2c_write(address); // посылаем в шину адрес читаемой ячейки
i2c_start(); // снова посылаем "старт" в шину
i2c_write(BMP085_W); // перевод в режим чтения
msb=i2c_read(0); // принимаем данные с лини и сохраняем в переменную
i2c_stop(); // посылаем команду "стоп"

delay_ms(5); // пауза 10 мс
i2c_start(); // посылаем команду "старт" в шину i2c
i2c_write(BMP085_R); // посылаем в шину адрес устройства
i2c_write(address+1); // посылаем в шину адрес читаемой ячейки
i2c_start(); // снова посылаем "старт" в шину
i2c_write(BMP085_W); // перевод в режим чтения
lsb=i2c_read(0); // принимаем данные с лини и сохраняем в переменную
i2c_stop(); // посылаем команду "стоп"

delay_ms(5); // пауза 10 мс
i2c_start(); // посылаем команду "старт" в шину i2c
i2c_write(BMP085_R); // посылаем в шину адрес устройства
i2c_write(address+2); // посылаем в шину адрес читаемой ячейки
i2c_start(); // снова посылаем "старт" в шину
i2c_write(BMP085_W); // перевод в режим чтения
lsb=i2c_read(0); // принимаем данные с лини и сохраняем в переменную
i2c_stop(); // посылаем команду "стоп"

delay_ms(5); // пауза 10 мс
data = msb; // к переменной data присваиваем значение msb
data<<= 8; // сдвигаем на 8 бит влево
data|=lsb; // прибавляем ещё значение lsb
data<<=8; // опять сдвигаем на 8 бит влево
data|=xlsb; // и прибавляем ещё значение xlsb
data>>=(8-OSS);
return data; // возврощаем значение прочитаного
}

/*** Чтение калибровачных данных из Eeprom BMP085 ***/
void BMP085calibration(void) {
AC1=BMP_read_2_bytes(0xAA);
AC2=BMP_read_2_bytes(0xAC);
AC3=BMP_read_2_bytes(0xAE);
AC4=BMP_read_2_bytes(0xB0);
AC5=BMP_read_2_bytes(0xB2);
AC6=BMP_read_2_bytes(0xB4);
B1=BMP_read_2_bytes(0xB6);
B2=BMP_read_2_bytes(0xB8);
MB=BMP_read_2_bytes(0xBA);
MC=BMP_read_2_bytes(0xBC);
MD=BMP_read_2_bytes(0xBE);

}

/*********** Чтение температуры из BMP085 ***********/
long BMP_read_temp(void) {
i2c_start();
i2c_write(BMP085_R);
i2c_write(0xF4);
i2c_write(0x2E);
delay_ms(5);
i2c_stop();
delay_ms(5);
return BMP_read_2_bytes(0xF6);
}

/*********** Чтение давления из BMP085 **************/
long BMP_read_pressure(void) {
i2c_start();
i2c_write(BMP085_R);
i2c_write(0xF4);
i2c_write(0x34 | (OSS << 6));
i2c_stop();
delay_ms(2 + (3<<OSS));
return BMP_read_3_bytes(0xF6);
}

/*********** Конвертация данных BMP085 **************/
void BMP085_convert(unsigned long *pressure,long *temperature) {
long x1, x2, x3, b3, b5 ,b6, ut, up, p;
unsigned long b4, b7;
summa++;
ut = BMP_read_temp();
up = BMP_read_pressure();

x1 = (((long) ut - (long) AC6) * (long) AC5) >> 15;
x2 = ((long) MC << 11) / (x1 + MD);

b5 = x1 + x2;
*temperature = ((b5 + 8) >> 4);

b6 = b5 - 4000;
x1 = (B2 * ((b6 * b6) >> 12)) >> 11;
x2 = (AC2 * b6) >> 11;
x3 = x1 +x2;
b3 = ((((long)AC1 *4 + x3) <<OSS) + 2) >> 2;
x1 = (AC3* b6) >> 13;
x2 = (B1 * ((b6*b6) >> 12) ) >> 16;
x3 = ((x1 + x2) + 2) >> 2;
b4 = (AC4 * (unsigned long) (x3 + 32768)) >> 15;
b7 = ((unsigned long)up - b3) * (50000>>OSS);
if (b7 < 0x80000000) {
p = (b7 << 1) / b4; }

else{
p = (b7 / b4) << 1; };

x1 = (p >> 8)*(p >> 8);
x1 = (x1 * 3038) >> 16;
x2 = (-7357 * p) >> 16;

pres_temp= p + ((x1 + x2 + 3791) >> 4); //press in Pa
pres_temp*=1000; //для отображения с десятыми долями на моем устройстве.
pres_temp/= 13332; //надо делить на 133.322
pres_temp_1 += pres_temp;
if (summa>=50) {
*pressure = (pres_temp_1/50);
pres_temp_1 = 0;
summa=0;
};
}

// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void) {
TCNT2=0x83;
timer_1++;
if (timer_1>=100) {
timer_1 = 0;
timer_2++;
BMP085_convert(&pressur_1,&temperatur_1);
pressur = pressur_1;
temperatur = temperatur_1;
};
}

void main(void)
{

// Declare your local variables here
// Graphic LCD initialization data

GLCDINIT_t glcd_init_data;

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: Normal top=0xFF
// OC2A output: Disconnected
// OC2B output: Disconnected

ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x04;
TCNT2=0x83;
OCR2A=0x00;
OCR2B=0x00;

// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x01;

// I2C Bus initialization
// I2C Port: PORTC
// I2C SDA bit: 4
// I2C SCL bit: 5
// Bit Rate: 100 kHz
// Note: I2C settings are specified in the
// Project|Configure|C Compiler|Libraries|I2C menu.

i2c_init();

// Graphic LCD initialization
// The PCD8544 connections are specified in the
// Project|Configure|C Compiler|Libraries|Graphic LCD menu:
// SDIN - PORTB Bit 6
// SCLK - PORTB Bit 7
// D /C - PORTD Bit 5
// /SCE - PORTD Bit 6
// /RES - PORTD Bit 7


// Specify the current font for displaying text
glcd_init_data.font=font5x7;
// No function is used for reading
// image data from external memory

glcd_init_data.readxmem=NULL;
// No function is used for writing
// image data to external memory

glcd_init_data.writexmem=NULL;
// Set the LCD temperature coefficient
glcd_init_data.temp_coef=PCD8544_DEFAULT_TEMP_COEF;
// Set the LCD bias
glcd_init_data.bias=PCD8544_DEFAULT_BIAS;
// Set the LCD contrast control voltage VLCD
glcd_init_data.vlcd=PCD8544_DEFAULT_VLCD;

glcd_init(&glcd_init_data);

BMP085calibration();

// Global enable interrupts
#asm("sei")

while (1)
{

glcd_putcharxy(0,0,pressur/1000+0x30);
glcd_putchar((pressur%1000)/100+0x30);
glcd_putchar((pressur%100)/10+0x30);
glcd_outtext(",");
glcd_putchar(pressur%10+0x30);
glcd_outtext(" mm.pt.ct");
glcd_putcharxy(0,8,temperatur/100+0x30);
glcd_putchar((temperatur%100)/10+0x30);
glcd_outtext(",");
glcd_putchar(temperatur%10+0x30);
glcd_outtext(" 'C");
glcd_putcharxy(0,16,timer_2/10000+0x30);
glcd_putchar((timer_2%10000)/1000+0x30);
glcd_putchar((timer_2%1000)/100+0x30);
glcd_putchar((timer_2%100)/10+0x30);
glcd_putchar(timer_2%10+0x30);


}
}
DSC_0579.JPG
Датчик BMP085
DSC_0575.JPG
В работе

bavbav
Сообщения: 160
Зарегистрирован: 09 июн 2009, 21:30
Контактная информация:

Re: AVR для начинающих.

Сообщение bavbav » 14 дек 2014, 21:11

Алексей, здравствуйте.А возможно сделать вариант под BMP180?

Alexl81
Сообщения: 997
Зарегистрирован: 10 окт 2010, 11:09
Откуда: Россия, Челябинская область.
Контактная информация:

Re: AVR для начинающих.

Сообщение Alexl81 » 15 дек 2014, 09:18

bavbav писал(а):Алексей, здравствуйте.А возможно сделать вариант под BMP180?
Здравствуйте. Вроде как BMP085 и BMP180 идентичны, с данной прошивкой BMP180 должен работать. Попробуйте.

bavbav
Сообщения: 160
Зарегистрирован: 09 июн 2009, 21:30
Контактная информация:

Re: AVR для начинающих.

Сообщение bavbav » 15 дек 2014, 13:10

А можно прошивку в виде hex файла и фьюзы

Alexl81
Сообщения: 997
Зарегистрирован: 10 окт 2010, 11:09
Откуда: Россия, Челябинская область.
Контактная информация:

Re: AVR для начинающих.

Сообщение Alexl81 » 15 дек 2014, 20:08

fuse_atmega328.jpg
fuse_ATmega328P
BMP085_I2C_Nokia5110.rar
hex_ATmega328P
(6.92 КБ) 254 скачивания
fuse_atmega8A.jpg
fuse_ATmega8A
BMP085_I2C.rar
hex_ATmega8A
(3.55 КБ) 263 скачивания
К ATmega8A подключается ЖКИ 1602:
// RS - PORTD Bit 5
// RD - PORTD Bit 6
// EN - PORTD Bit 7
// D4 - PORTB Bit 2
// D5 - PORTB Bit 3
// D6 - PORTB Bit 4
// D7 - PORTB Bit 5
Датчик подключается к:
// I2C Port: PORTC
// I2C SDA bit: 4
// I2C SCL bit: 5

bavbav
Сообщения: 160
Зарегистрирован: 09 июн 2009, 21:30
Контактная информация:

Re: AVR для начинающих.

Сообщение bavbav » 15 дек 2014, 20:13

Алексей, большое спасибо, пошел заказывать модуль.

bavbav
Сообщения: 160
Зарегистрирован: 09 июн 2009, 21:30
Контактная информация:

Re: AVR для начинающих.

Сообщение bavbav » 16 дек 2014, 20:00

В догонку, Алексей хотел спросить, не занимались ли детектором газа на базе MQ-4 ?

Alexl81
Сообщения: 997
Зарегистрирован: 10 окт 2010, 11:09
Откуда: Россия, Челябинская область.
Контактная информация:

Re: AVR для начинающих.

Сообщение Alexl81 » 16 дек 2014, 20:27

bavbav писал(а):В догонку, Алексей хотел спросить, не занимались ли детектором газа на базе MQ-4 ?
Здравствуйте. Нет, в наличии нет.

bavbav
Сообщения: 160
Зарегистрирован: 09 июн 2009, 21:30
Контактная информация:

Re: AVR для начинающих.

Сообщение bavbav » 25 дек 2014, 22:37

Алексей, конвертер сигналов делали на 4х транзисторах? Платой в .lay не поделитесь?

Ответить

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя