Chip type : ATmega32A
Program type : Application
AVR Core Clock frequency: 1,000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 512
*****************************************************/
#include <stdio.h>
#include <mega32a.h>
#include <delay.h>
#include <I2C_user.h>
// TWI functions
#include <twi.h>
// Declare your global variables here 7
// ОПРЕДЕЛЕНИЯ ДЛЯ ПОКЛЮЧЕНИЯ LCD C55
#define lcd_sclk PORTD.3 // nokia lcd sclk
#define lcd_sda PORTD.4 // nokia lcd sda
#define lcd_dc PORTD.6 // nokia lcd d/c
#define lcd_cs PORTB.0 // nokia lcd cs
#define lcd_res PORTB.1 // nokia lcd res
// ОПРЕДЕЛЕНИЯ ДЛЯ ПОДКЮЧЕНИЯ АКСЕЛЛЕРОМЕТРА
#define AdressConst 0b00011101 //Постоянная часть адреса ведомого устройства MMA7455
#define int_axe PIND.7 //вывод готовноси преобразования MMA7455
#define blink PORTA.0 //ИНДИКАЦИЯ ГОТОВНОСТИ ПРЕОБРАЗОВАНИЯ ДАНЫХ MMA7455
//0x06; // переменная для регистра оси X
//0x07; // переменная для значний оси Y
//0x08; // переменная для значний оси Z
//ПЕРЕМЕННЫЕ ДЛЯ lcd
unsigned char byteforlcd;
unsigned int lcdc55=918; //количество столбцов в экране нокиа c55
char c;
//------------------------------------------------------------------------------
//ПЕРЕМЕННЫЕ ДЛЯ АКСЕЛЛЕРОМЕТРА
unsigned char str [11]; //буфер хранения строки выводимой на дисплей
unsigned char data_x; // переменная для значний оси X
unsigned char data_y; // переменная для значний оси Y
unsigned char data_z; // переменная для значний оси Z
unsigned char data_r; // переменная для хранения прочитаных данных
//----------------------------------------------------------------------------
flash unsigned char Font_6x8_Data[][6] =
{
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void init_lcd(void); // инициализация LCD
void lcd_clear(void); // очистка экрана
void lcd_write_command(void); // отправка комманды на LCD
void lcd_write_dorc(void); //отправка 8 бит по программной шине LCD (SPI)
void lcd_write_data(void); // передача данных в диплей
void lcd_gotoxy(unsigned char xlcd, unsigned char ylcd); //установка курсора на Х и У LCD
void lcd_putch (unsigned char c); // отправка одно сомвола в LCD
void lcd_putstr (char *s); // отправка строки из буфера (str) в LCD
//--Функции для LCD----------------------------
void init_lcd(void)
{
lcd_dc=0;
lcd_cs=1;
lcd_res=0;
delay_us (500);
lcd_res=1;
delay_us (500);
byteforlcd=0x21; //включения питания, ExtCommandSet
lcd_write_command();
byteforlcd=0x09; //Внутренний HV поколения x3
lcd_write_command();
byteforlcd=0xC3; //Set Vop
lcd_write_command();
byteforlcd=0x16; //Смещение п = 2 / / 15
lcd_write_command();
byteforlcd=0x06; //Температурный коэфф 2
lcd_write_command();
byteforlcd=0x20; //StandartCommandSet
lcd_write_command();
byteforlcd=0x0C; //нормальном режиме, отображение неинвертированного
lcd_write_command();
}
//////////////////////////////////////////////////////////////
void lcd_clear(void)
{
unsigned int buf=0;
lcd_gotoxy (0x00,0x00);
for (buf=0;buf<lcdc55;buf++) {
byteforlcd=0;
lcd_write_data();
}
}
//////////////////////////////////////////////////////////////
void erase_line(unsigned char num_x,unsigned char num_y)
{
unsigned int buf=0;
lcd_gotoxy (num_x,num_y);
for (buf=num_x;buf<98;buf++)
{
byteforlcd=0;
lcd_write_data();
}
}
//////////////////////////////////////////////////////////////
void lcd_write_command(void)
{
lcd_dc=0; // передача команды в регистр
lcd_cs=0; // включение контроллера
lcd_write_dorc();
lcd_cs=1; // отключение контроллера
}
//////////////////////////////////////////////////////////////
void lcd_write_data(void)
{
lcd_dc=1; // передача данных в диплей
lcd_cs=0; // chip enabled
lcd_write_dorc();
lcd_cs=1; // chip disabled
}
//////////////////////////////////////////////////////////////
void lcd_write_dorc(void) // serial write data or command subroutine
{
for (c=8;c>0;c--) {
lcd_sclk=0;
if ((byteforlcd&0x80)==0){
lcd_sda=0;}
else {
lcd_sda=1;}
lcd_sclk=1;
byteforlcd=byteforlcd<<1;}
}
//////////////////////////////////////////////////////////////
void lcd_gotoxy (unsigned char xlcd, unsigned char ylcd) // Nokia LCD Position cursor
{
byteforlcd=(0x40|(ylcd&0x07)); // Y axe initialisation: 0100 0yyy
lcd_write_command();
byteforlcd=(0x80|(xlcd&0x7f)); // X axe initialisation: 1xxx xxxx
lcd_write_command();
}
//////////////////////////////////////////////////////////////
void lcd_putch (unsigned char c) //вызывается в 198 строке
{ //вывод символа в текущую поз. курсора
unsigned char i=0;
for (i=0; i<6; i++) //ширина буквы 6!!! пикс
{
byteforlcd=(Font_6x8_Data[c][i]);
lcd_write_data(); //
}
//пропускаем пиксел между буквами!!!!!!!
byteforlcd=0x00;
lcd_write_data(); // если убрать, цифры будут расположены вплотную. При увеличении 1цифры тоже сливаются при увел. 0х00 мусор
}
//////////////////////////////////////////////////////////////
void lcd_putstr (char *s) //void lcd_putstr (const char *s)
{
while (*s) //выполнять пока *s>0
{
lcd_putch(*s);
s++;
}
}
//функции для акселерометра------------------------------------
int WriteByte(unsigned char address,unsigned char data) /*Запись по адресу (adress) байта (data)*/
{
/*****УСТАНАВЛИВАЕМ СВЯЗЬ С ВЕДОМЫМ********/
do
{
//Инициализация Регистра управления шиной в Блоке управления
/*Перед началом передачи данных необходимо сформировать т.н. условие начала. В состоянии покоя линии SCL и SDA находятся на высоком уровне. Ведущее устройство (Контроллер AVR в нашем примере), которое хочет начать передачу данных, изменяет состояние линии SDA к низкому уровню. Это и есть условие начала передачи данных.*/
/*
а)Сброс флага прерывания TWINT (Флаг TWINT сбрасывается программно путем записи в него логической 1) для разрешения начала новой передачи данных
б)Уст. бит условия СТАРТ
в)Уст. бит разрешения работы TWI
*/
TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
//Ждем, пока шина даст добро (возможно, линия пока еще занята, ждем)
//TWINT бит устанавливается аппаратно, если TWI завершает текущее задание и ожидает реакции программы
while(!(TWCR & (1<<TWINT)));
/*Проверяем регистр статуса, а точнее биты TWS3-7,
которые доступны только для чтения. Эти пять битов
отражают состояние шины. TWS2-0 «отсекаем» с помощью операции «И 0xF8». Если TWS7-3 = 0x08, то СТАРТ был успешным.*/
if((TWSR & 0xF8) != TW_START)
return false;
/*К шине I2C может быть подключено множество подчиненных устройств (к примеру, много микросхем внешней памяти EEPROM). Для того, чтобы все микросхемы и контроллер знали, от кого и кому передается информация, в протоколе реализована Адресация ведомых устройств. В каждой микросхеме, предназначенной для работы с I2C, на заводе "зашит" определенный адрес. Мы этот адрес передаем по всей шине, т.е. всем ведомым. Каждый ведомый получает этот адрес и смотрит, типа мой это или чужой. Если мой, то О КРУТО, со мной хочет работать контроллер AVR. Так вот и происходит "рукопожатие" между ведущим и ведомым.*/
/*Так вот, мы хотим работать с микросхемой памяти 24LC64, поэтому по шине нам надо передать ее адрес. Она узнает свой адрес, и будет знать, что данные на запись адресуются именно ей. А остальные микросхемы, если они есть, эти данные будут просто игнорировать.*/
/*Постоянная часть адреса 24LC64 – 1010 (см. даташит на 24XX64), 3 бита - переменные (если вдруг мы захотим подключить несколько одинаковых микросхем c одинаковыми заводскими адресами, они пригодятся; в ином(нашем) случае выставляем нули), далее бит 0 - если хотим записывать в память или 1 - если читаем данные из памяти I2C EEPROM*/
//TWDR = 0b1010‘000‘0;
TWDR = (AdressConst<<1) + (WRITEFLAG);
/*Говорим регистру управления, что мы хотим передать данные, содержащиеся в регистре данных TWDR*/
TWCR=(1<<TWINT)|(1<<TWEN);
//Ждем окончания передачи данных
while(!(TWCR & (1<<TWINT)));
/*Если нет подтверждения от ведомого, делаем все по-новой (либо неполадки с линией, либо ведомого с таким адресом нет).
Если же подтверждение поступило, то регистр статуса установит биты в 0x18=TW_MT_SLA_ACK (в случае записи) или 0x40=TW_MR_SLA_ACK (в случае чтения).
Грубо говоря, если TW_MT_SLA_ACK, то ведомый "говорит" нам, что его адрес как раз 1010’000 и он готов для записи (чтения, если TW_MR_SLA_ACK).*/
}while((TWSR & 0xF8) != TW_MT_SLA_ACK);
/*Здесь можем уже уверенно говорить, что ведущий и ведомый друг друга видят и понимают. Вначале скажем нашей микросхеме памяти, по какому адресу мы хотим записать байт данных*/
/*****ПЕРЕДАЕМ АДРЕС ЗАПИСИ********/
/*Записываем в регистр данных разряд адреса */
TWDR=(address);
//..и передаем его
TWCR=(1<<TWINT)|(1<<TWEN);
//ждем окончания передачи
while(!(TWCR & (1<<TWINT)));
/*Проверяем регистр статуса, принял ли ведомый данные. Если ведомый данные принял, то он передает "Подтверждение", устанавливая SDA в низкий уровень. Блок управления, в свою очередь, принимает подтверждение, и записывает в регистр статуса 0x28= TW_MT_DATA_ACK. В противном случае 0x30= TW_MT_DATA_NACK */
if((TWSR & 0xF8) != TW_MT_DATA_ACK)
return false;
/*****ЗАПИСЫВАЕМ БАЙТ ДАННЫХ********/
//Аналогично, как и передавали адрес, передаем байт данных
TWDR=(data);
TWCR=(1<<TWINT)|(1<<TWEN);
while(!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_DATA_ACK)
return false;
/*Устанавливаем условие завершения передачи данных (СТОП)
(Устанавливаем бит условия СТОП)*/
TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
//Ждем установки условия СТОП
while(TWCR & (1<<TWSTO));
return true;
}
int ReadByte(unsigned char address) /*чтение по дресу (adress)*/
{
//Точно такой же кусок кода, как и в eeWriteByte...
/*****УСТАНАВЛИВАЕМ СВЯЗЬ С ВЕДОМЫМ********/
do
{
TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while(!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_START)
return false;
TWDR =(AdressConst<<1) + (WRITEFLAG);
TWCR=(1<<TWINT)|(1<<TWEN);
while(!(TWCR & (1<<TWINT)));
}while((TWSR & 0xF8) != TW_MT_SLA_ACK);
/*****ПЕРЕДАЕМ АДРЕС ЧТЕНИЯ********/
TWDR=(address);
TWCR=(1<<TWINT)|(1<<TWEN);
while(!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_DATA_ACK)
return false;
/*****ПЕРЕХОД В РЕЖИМ ЧТЕНИЯ********/
/*Необходимо опять «связаться» с ведомым, т.к. ранее мы отсылали адресный пакет (slaveAddressConst<<4) + (slaveAddressVar<<1) + WRITEFLAG, чтобы записать адрес чтения байта данных. А теперь нужно перейти в режим чтения (мы же хотим прочитать байт данных), для этого отсылаем новый пакет (slaveAddressConst<<4) + (slaveAddressVar<<1) + READFLAG.*/
//Повтор условия начала передачи
TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
//ждем выполнения текущей операции
while(!(TWCR & (1<<TWINT)));
/*Проверяем статус. Условие повтора начала передачи (0x10=TW_REP_START) должно подтвердиться*/
if((TWSR & 0xF8) != TW_REP_START)
return false;
/*Записываем адрес ведомого (7 битов) и в конце бит чтения (1)*/
//TWDR=0b1010’000’1;
TWDR =(AdressConst<<1) + (READFLAG);
//Отправляем..
TWCR=(1<<TWINT)|(1<<TWEN);
while(!(TWCR & (1<<TWINT)));
/*Проверяем, нашелся ли ведомый с адресом 1010’000 и готов ли он работать на чтение*/
if((TWSR & 0xF8) != TW_MR_SLA_ACK)
return false;
/*****СЧИТЫВАЕМ БАЙТ ДАННЫХ********/
/*Начинаем прием данных с помощью очистки флага прерывания TWINT. Читаемый байт записывается в регистр TWDR.*/
TWCR=(1<<TWINT)|(1<<TWEN);
//Ждем окончания приема..
while(!(TWCR & (1<<TWINT)));
/*Проверяем статус. По протоколу, прием данных должен оканчиваться без подтверждения со стороны ведущего (TW_MR_DATA_NACK = 0x58)*/
if((TWSR & 0xF8) != TW_MR_DATA_NACK)
return false;
/*Присваиваем переменной data значение, считанное в регистр данных TWDR*/
data_r=TWDR;
/*Устанавливаем условие завершения передачи данных (СТОП)*/
TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
//Ждем установки условия СТОП
while(TWCR & (1<<TWSTO));
//Возвращаем считанный байт
return data_r;
}
void init_axe (void)
{
WriteByte (0x16,0x01);}
void reset_int (void) // сброс регистра прерывания для начала нового прерывания
{
WriteByte (0x17,0x03);
WriteByte (0x17,0x00);}
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=0
PORTA=0x00;
DDRA=0x01;
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=Out Func0=Out
// State7=T State6=T State5=T State4=T State3=T State2=T State1=0 State0=0
PORTB=0x00;
DDRB=0x03;
// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=Out Func5=In Func4=Out Func3=Out Func2=In Func1=In Func0=In
// State7=T State6=0 State5=T State4=0 State3=0 State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x58;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;
// USART initialization
// USART disabled
UCSRB=0x00;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// ADC initialization
// ADC disabled
ADCSRA=0x00;
// SPI initialization
// SPI disabled
SPCR=0x00;
// TWI initialization
// Mode: TWI Master
// Bit Rate: 62 kHz
twi_master_init(62);
// Global enable interrupts
#asm("sei")
init_lcd();
lcd_clear();
init_axe();
while (1)
{
PORTA.0=0;
delay_ms(500);
if (int_axe)
{
// отрисовка значений X
ReadByte(0x06);
data_x=data_r;
sprintf(str, "ОСЬ X= %u",data_x);//вывод значени переменой хранящней код
erase_line(36,0);
lcd_gotoxy(0,0);
lcd_putstr(str);
// отрисовка значений Y
ReadByte(0x07);
data_y=data_r;
sprintf(str, "ОСЬ Y= %u",data_y);//вывод значени переменой хранящней код
erase_line(36,1);
lcd_gotoxy(0,1);
lcd_putstr(str);
// отрисовка значений Z
ReadByte(0x08);
data_z=data_r;
sprintf(str, "ОСЬ Z= %u",data_z);//вывод значени переменой хранящней код
erase_line(36,2);
lcd_gotoxy(0,2);
lcd_putstr(str);
PORTA.0=1;
}
reset_int();
}
}