//main.c программа импульсного металлоискателя tracker-pi2 V1.0 за публичные усовершенствования технологии Geoscan Pulse//
//C / C++ компилятор IAR Embedded Workbench IDE AVR 7.30.4//
#include "iotiny2313a.h"
#include <ioavr.h>
#include <intrinsics.h>
#include <stdio.h>
#include <stdlib.h>
#include "ina90.h"
#include "lcd.h"
#include "timeout.h"
#include "hardware.h"
#include "global_var.h"
#define START_DELAY 500 //милисекунд для установления режимов усилителя по постоянному току
#define ENABLE_LCD // если включено - светодиоды не используются
#define ENABLE_SOUND
#define ENABLE_USART
#define OLD_AVERAGE_FILTER // усредняющий и помехоподавляющий фильтр
#define USE_MANUAL_TIME_TX // задать время накачки вручную - для особых датчиков
#define ManualTimeTX 0x75
#define BoardV3 // на плате 3 версии находятся ускоряющие конденсаторы 470пФ и открывающий вспомогательный транзистор в драйвере полевика
#ifdef BoardV3
#define CAP_BOOST_TIME 5 // -5us
#define TIME_GUARD 0x0c // 12us
#define START_TIME_TX 64 // 100us
#else
#define CAP_BOOST_TIME 0 // 0
#define TIME_GUARD 0x0a // 10 us
#define START_TIME_TX 0x41 // 65 us
#endif
#define UTC_DELAY_1 6
#define UTC_DELAY_2 6
#define baudrate 38400 // 57600; 115200; 128000
void LowBatIndicationLoop (void);
void __watchdog_init (void)
{
//запускаю сторожевой таймер на 2 секунды
__watchdog_reset ();
WDTCR |= ((1<<WDCE)|(1<<WDE));
WDTCR = (1<<WDE)|(7<<WDP0);
__watchdog_reset ();
}
void InitTimers (void)
{
TCCR1A = 0x00;
TCCR1B |= ((1<<CS10) | (1<<WGM12));
OCR1A = 58500; //50000+6; //0xc350; //0xc350;
TCCR0B |= (4<<CS00);
TIMSK |= ((1<<TOIE0) | (1<<OCIE1A));
ACSR |= (1<<ACIC);
}
void InitPorts (void)
{
PortPot |= (1<<Pot);
PortPotDir |= (1<<Pot);
PortKeys |= ((1<<Q2) | (1<<Q0) | (1<<Q1));
PortKeysDir |= ((1<<Q2) | (1<<Q0) | (1<<Q1));
PortSpeakerDir |= (1<<Speaker);
PortSys |= ((1<<Pot) | (1<<Q2) | (1<<Q0) | (1<<Q1) | (1<<BatMeter));
PortSysDir |= ((1<<Pot) | (1<<Q2) | (1<<Q0) | (1<<Q1) | (1<<Speaker));
}
void InitUsart (unsigned int baud)
{
UBRRH = (unsigned char)(baud>>
;
UBRRL = (unsigned char)baud;
UCSRB |= (1<<TXEN);
}
void USARTSendChar (unsigned char data)
{
#ifdef ENABLE_USART
while (!( UCSRA & (1<<UDRE))); // ждем, пока отправится предыдущий байт
UDR = data;
#endif //ENABLE_USART
}
void InitMode (void)
{
IntegratorCycleEnd = 0x00; // переменная глобальная, поэтому равна 0 после RESET
//устанавливаем начальные временные интервалы
TimeTX = START_TIME_TX-CAP_BOOST_TIME;
TimeGuardAfterTXOFF = 0; // переменная глобальная, поэтому равна 0 после RESET
TimeGuardAfterRXON = 0;// + CAP_BOOST_TIME;// + UTC_DELAY_1; // переменная глобальная, поэтому равна 0 после RESET
TimeIntegration = 0x10;
__enable_interrupt();
}
void GetPotPosition (void)
{
unsigned int counter = 0;
__disable_interrupt();
PortPotDir &= ~(1<<Pot); //переключаем выход на вход
PortPot &= ~(1<<Pot);
while (PinPot & (1<<Pot)) { counter += PositionAddStep; } //ждем, пока напряжение упадет до порогового
UDR = (unsigned char)counter;
PortPot |= (1<<Pot); //переключаем вход на выход
PortPotDir |= (1<<Pot);
counter -= PositionSub;
if ((counter > PositionMax) || (counter == 0)) counter = 1; // проверяем, не вылезло ли за пределы
Sensitivity = counter;
UDR = (unsigned char)Sensitivity;
}
__flash signed int segmentsDec[5]={10000,1000,100,10,1};
unsigned char String[5];
void CharToStringDec(signed int inp)
{
unsigned char i;
String[0]=String[1]=String[2]=String[3]=String[4]=0;
// перевод
for(i=0;i<5
{
if((inp-segmentsDec[i])>=0)
{
inp-=segmentsDec[i];
String[i]++;
}
else i++;
}
}
#ifdef ENABLE_LCD
static __flash char str01 [] = " -<>+ "; //+000
static __flash char str02 [] = "Wait"; //+000
void LCDBarUpdate (signed int level)
{
unsigned char col, pos;
signed int t;
if (level < 0) t = 0;
if (level < 256) t = (signed int)level;
else t = 255;
if (level >= threshold5) { ToneNumber = 5; }
else if (level >= threshold4) { ToneNumber = 4; }
else if (level >= threshold3) { ToneNumber = 3; }
else if (level >= threshold2) { ToneNumber = 2; }
else if (level >= threshold1) { ToneNumber = 1; }
else { ToneNumber = 0; }
if (++LCDPrescaler > 2)
{
LCDPrescaler = 0;
lcd_gotoxy(0,0);//здесь показать уровень
lcd_puts_p(str01);
if (level < 0) { lcd_putc('-'); }
else { lcd_putc(' '); }
CharToStringDec(level); // конвертация
for (unsigned char v=1; v<5; v++) lcd_putc(String[v]+0x30);
lcd_gotoxy(0,1);
col = (t+4
/ 16;//рассчитываем номер знакоместа для рисования палки
if (col>0) for (unsigned char z=0; z<col; z++) lcd_putc(0x05);//рисуем несколько полностью закрашенных знакомест
//рассчитываем номер символа для отображения в знакоместе //5 вариантов
pos = (t+4
- (col*16); // остаток
pos = (pos)/3;
lcd_putc(pos); //0x00+
for (unsigned char t=0; t<16; t++) lcd_putc(' '); //не чистим экран, а заполняем пробелами
}
}
#endif //ENABLE_LCD
void DelayUnits (unsigned long time)
{
while (time--) {}
}
#pragma vector = TIMER1_COMPA_vect //вызывается раз в 5мс
__interrupt void KeyDrive (void)
{
unsigned int ICRData = ICR1; //получаем данные о времени срабатывания компаратора
PortKeys &= ~(1<<Q1); //выключаем первый усилитель
DelayUnits (10);
PortKeys &= ~(1<<Q0); //включаем накачку катушки
DelayUnits (TimeTX);
PortKeys |= (1<<Q0); //выключаем накачку катушки
DelayUnits (TimeGuardAfterTXOFF);
PortKeys |= (1<<Q1); //включаем первый усилитель
DelayUnits (TimeGuardAfterRXON);
PortKeys &= ~(1<<Q2); //включаем интегратор
DelayUnits (TimeIntegration);
PortKeys |= (1<<Q2); //выключаем интегратор
IntegratorCycleCount++;
Integrator += ICRData;
__enable_interrupt(); //разрешить прерывания
if (IntegratorCycleCount > 7)
{
IntegratorCycleCount = 0;
Integrator = (Integrator >> 3); // деление на 8
ReceivedSignal = (unsigned int)Integrator;
UDR = ReceivedSignal>>8;
IntegratorCycleEnd = 0xFF;
Integrator = 0;
}
GetPotPosition ();
__watchdog_reset ();
}
unsigned char SoundCycleCount;
#pragma vector=TIMER0_OVF_vect
__interrupt void Sound (void)
{
TCNT0 = 0xFE; // перезагрузить таймер
if ((ToneNumber != 0) && (SoundCycleCount == 0))
{
SoundCycleCount = 16 - ToneNumber;
#ifdef ENABLE_SOUND
if (PortSpeaker & (1<<Speaker)) PortSpeaker &= ~(1<<Speaker); // speaker toggle
else PortSpeaker |= (1<<Speaker);
#endif //ENABLE_SOUND
}
if (SoundCycleCount) SoundCycleCount--;
#ifdef ENABLE_SOUND
if (ToneNumber == 0) PortSpeaker &= ~(1<<Speaker); // не потребляем динамиком лишний ток
#endif //ENABLE_SOUND
}
void LowBatIndicationLoop (void) // отсюда никогда не выходим
{
TimeTX = 0; //Полная накачка уже ни к чему
PortSysDir &= ~(1<<Q0); //Выключаем ключ совсем - Полная накачка уже ни к чему
while (1)// батарея разряжена
{
__delay_cycles((CtrlClockRate/1000)*500);
if (ToneNumber == 1) ToneNumber =0;
else ToneNumber = 1;
}
}
int main (void)
{
signed int Ka=0, Kb=0, Kc=0, Kd=0, temp=0, tempdebug=0;
InitPorts ();
#ifdef ENABLE_LCD
lcd_init(LCD_DISP_ON);
lcd_clrscr();
lcd_gotoxy(6,0);
lcd_puts_p(str02);
#endif //ENABLE_LCD
#ifdef ENABLE_USART
InitUsart (((CtrlClockRate/16)/baudrate)-1);
#endif //ENABLE_USART
InitTimers ();
InitMode ();
__delay_cycles((CtrlClockRate/1000)*START_DELAY); // стартовая задержка
__watchdog_init ();
unsigned int tem;
for (unsigned char i=0; i<8; i++)
{
while (IntegratorCycleEnd == 0) {} // ждем пока пройдет интегрирование
EchoSumm = EchoSumm + ReceivedSignal;
tem = ReceivedSignal >> 8;
USARTSendChar ((unsigned char)tem);
USARTSendChar ((unsigned char)ReceivedSignal);
IntegratorCycleEnd = 0;
}
USARTSendChar ((unsigned char)EchoSumm);
EchoSumm = EchoSumm >> 8; // деление на 256
Echo = (unsigned char)(EchoSumm);
USARTSendChar (Echo);
Echo -= 0x32;
USARTSendChar (Echo); // эхо, полученное при калибровке
if (Echo >= 0x19) // катушка в порядке, эхо достаточной величины
{
if (Echo <= 0x37) {Ka = 0x19; Kb = 0x37; Kc = 0xA0; Kd = 0x8C; }
else if (Echo <= 0x4B) {Ka = 0x37; Kb = 0x4B; Kc = 0x8C; Kd = 0x67; }
else if (Echo <= 0x52) {Ka = 0x4B; Kb = 0x52; Kc = 0x67; Kd = 0x52; }
else if (Echo <= 0x5F) {Ka = 0x52; Kb = 0x5F; Kc = 0x52; Kd = 0x41; }
temp = Echo - Ka;
temp = temp * (Kd - Kc);
temp = Kc + (temp / (Kb - Ka));
#ifndef USE_MANUAL_TIME_TX
TimeTX = temp - CAP_BOOST_TIME; //устанавливаем рабочие тайминги
if (Echo >= 0x60) TimeTX = 0x41 - CAP_BOOST_TIME;
#endif
#ifdef USE_MANUAL_TIME_TX
TimeTX = ManualTimeTX;
#endif //USE_MANUAL_TIME_TX
TimeGuardAfterTXOFF = TIME_GUARD;
TimeGuardAfterRXON = 0x00;// + CAP_BOOST_TIME;// + UTC_DELAY_1 + UTC_DELAY_2;
TimeIntegration = 0x32;
USARTSendChar (TimeTX); // вычисленное время накачки
for (unsigned char i=0; i<10; i++) // пропускаем 10 циклов для устаканивания
{
while (IntegratorCycleEnd == 0) {} // пропускаем 1 цикл
IntegratorCycleEnd = 0;
}
while (IntegratorCycleEnd == 0) {} // пропускаем 1 цикл, этого достаточно
IntegratorCycleEnd = 0;
unsigned int tem;
EchoSumm = 0;
for (unsigned char i=0; i<32; i++)
{
while (IntegratorCycleEnd == 0) {} // ждем пока пройдет интегрирование
tem = ReceivedSignal >> 8;
USARTSendChar ((unsigned char)tem);
USARTSendChar ((unsigned char)ReceivedSignal);
EchoSumm += ReceivedSignal;
IntegratorCycleEnd = 0;
}
EchoSumm = EchoSumm >> 5; // деление на 32
BaseValue = (unsigned int)EchoSumm; // получили базовое значение при отсутствии металла
tem = BaseValue >> 8;
USARTSendChar ((unsigned char)tem);
USARTSendChar ((unsigned char)BaseValue);
USARTSendChar (BaseValue>>
; //базовое значение
while (1) // основной цикл обнаружения металла
{
while (IntegratorCycleEnd == 0) {} // ждем пока пройдет интегрирование
IntegratorCycleEnd = 0;
#ifdef OLD_AVERAGE_FILTER //усреднитель сигнала
EchoSumm = 0;
for (unsigned char z=0; z<(ArrayLength-1); z++) { ArrayReceivedSignal [z] = ArrayReceivedSignal [z+1]; } // сдвинули массив к 0 ячейке
ArrayReceivedSignal [ArrayLength-1] = ReceivedSignal; // в последнюю ячейку вносим свежее значение
for (unsigned char z=0; z<ArrayLength; z++) EchoSumm += ArrayReceivedSignal [z]; // суммируем последние показания
ReceivedSignal = (unsigned int)(EchoSumm / ArrayLength);
#endif //OLD_AVERAGE_FILTER
UDR = ReceivedSignal;
tem = ReceivedSignal >> 8;
USARTSendChar ((unsigned char)ReceivedSignal);
USARTSendChar ((unsigned char)tem);
temp = ReceivedSignal - BaseValue; // сравнение с опорным значением
tempdebug = temp + 127;
if (tempdebug > 255) tempdebug = 255;
if (tempdebug < 0) tempdebug = 0;
UDR = tempdebug;
temp += temp; // разницу удваиваем со знаком
temp += temp; // разницу удваиваем со знаком
temp = 250;
temp = temp / ((signed int)Sensitivity);
USARTSendChar ((unsigned char)Sensitivity);
#ifdef ENABLE_LCD // тут своя процедура вывода полосы
if (temp < -4
temp = -48; // следим за рамками
if (temp > 999
temp = 9999;
if (++LCDPrescaler > 2)
LCDPrescaler = 0;
LCDBarUpdate (temp);
#endif //ENABLE_LCD
}
}
else LowBatIndicationLoop ();
}
----------------------
/*оптимизировано для меньшего размера кода, для случая если 4 бита, RS и E находятся в пределах 1 порта*/
#include <ioavr.h>
//#include <avr/pgmspace.h>
#include "timeout.h"
#include <intrinsics.h>
#include "lcd_hw.h"
#include "lcd.h"
__flash char SymbolCGRAM[48] = {
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
// символ №0
0x10, /* ...$.... */
0x10, /* ...$.... */
0x10, /* ...$.... */
0x10, /* ...$.... */
0x10, /* ...$.... */
0x10, /* ...$.... */
0x10, /* ...$.... */
0x10, /* ...$.... */
// символ №1
0x18, /* ...$$... */
0x18, /* ...$$... */
0x18, /* ...$$... */
0x18, /* ...$$... */
0x18, /* ...$$... */
0x18, /* ...$$... */
0x18, /* ...$$... */
0x18, /* ...$$... */
// символ №2
0x1C, /* ...$$$.. */
0x1C, /* ...$$$.. */
0x1C, /* ...$$$.. */
0x1C, /* ...$$$.. */
0x1C, /* ...$$$.. */
0x1C, /* ...$$$.. */
0x1C, /* ...$$$.. */
0x1C, /* ...$$$.. */
// символ №3
0x1E, /* ...$$$$. */
0x1E, /* ...$$$$. */
0x1E, /* ...$$$$. */
0x1E, /* ...$$$$. */
0x1E, /* ...$$$$. */
0x1E, /* ...$$$$. */
0x1E, /* ...$$$$. */
0x1E, /* ...$$$$. */
// символ №4
0x1F, /* ...$$$$$ */
0x1F, /* ...$$$$$ */
0x1F, /* ...$$$$$ */
0x1F, /* ...$$$$$ */
0x1F, /* ...$$$$$ */
0x1F, /* ...$$$$$ */
0x1F, /* ...$$$$$ */
0x1F, /* ...$$$$$ */
// символ №5
};
/* compatibilty macros for old style */
/*
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
*/
/*
** constants/macros
*/
void lcd_e_high(void)
{
LCD_DATA_PORT |= (1<<LCD_E_PIN);
}
void lcd_e_low(void)
{
LCD_DATA_PORT &= ~(1<<LCD_E_PIN);
}
void lcd_cmd_mode(void)
{
LCD_DATA_PORT &= ~(1<<LCD_RS_PIN); // RS=0 command mode
}
void lcd_data_mode(void)
{
LCD_DATA_PORT |= (1<<LCD_RS_PIN); // RS=1 data mode
}
void lcd_data_port_out(void)
{ /* defines all data pins as output */
LCD_DDR_PORT |= (1<<LCD_DATA_PIN_D7) | (1<<LCD_DATA_PIN_D6) | (1<<LCD_DATA_PIN_D5) | (1<<LCD_DATA_PIN_D4) | (1<<LCD_RS_PIN) | (1<<LCD_E_PIN);
//LCD_DDR_PORT |= (1<<LCD_RS_PIN) | (1<<LCD_E_PIN);
/*
LCD_DDR_PORT |= (1<<LCD_DATA_PIN_D7);
LCD_DDR_PORT |= (1<<LCD_DATA_PIN_D6);
LCD_DDR_PORT |= (1<<LCD_DATA_PIN_D5);
LCD_DDR_PORT |= (1<<LCD_DATA_PIN_D4);
*/
}
#if LCD_LINES==1
#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_1LINE
#else
#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_2LINES
#endif
/*
** function prototypes
*/
static void lcd_e_toggle(void);
static void lcd_out_high(u08 d);
//static void lcd_out_low(u08 d);
/*
** local functions
*/
/*
static void lcd_out_low(u08 d)
{ // output low nibble
if (d&0x0
LCD_DATA_PORT_D7 |= (1<<LCD_DATA_PIN_D7);
else LCD_DATA_PORT_D7 &= ~(1<<LCD_DATA_PIN_D7);
if (d&0x04) LCD_DATA_PORT_D6 |= (1<<LCD_DATA_PIN_D6);
else LCD_DATA_PORT_D6 &= ~(1<<LCD_DATA_PIN_D6);
if (d&0x02) LCD_DATA_PORT_D5 |= (1<<LCD_DATA_PIN_D5);
else LCD_DATA_PORT_D5 &= ~(1<<LCD_DATA_PIN_D5);
if (d&0x01) LCD_DATA_PORT_D4 |= (1<<LCD_DATA_PIN_D4);
else LCD_DATA_PORT_D4 &= ~(1<<LCD_DATA_PIN_D4);
}
*/
static void lcd_out_high(u08 d) // output high nibble
{
unsigned char temp;
LCD_DATA_PORT &= ~((1<<LCD_DATA_PIN_D7) | (1<<LCD_DATA_PIN_D6) | (1<<LCD_DATA_PIN_D5) | (1<<LCD_DATA_PIN_D4));//сбросили DATA
temp = 0xF0 & d; // маскируем младшие биты на всякий случай
LCD_DATA_PORT |= temp;
/*
if (d&0x80) LCD_DATA_PORT |= (1<<LCD_DATA_PIN_D7);
else LCD_DATA_PORT &= ~(1<<LCD_DATA_PIN_D7);
if (d&0x40) LCD_DATA_PORT |= (1<<LCD_DATA_PIN_D6);
else LCD_DATA_PORT &= ~(1<<LCD_DATA_PIN_D6);
if (d&0x20) LCD_DATA_PORT |= (1<<LCD_DATA_PIN_D5);
else LCD_DATA_PORT &= ~(1<<LCD_DATA_PIN_D5);
if (d&0x10) LCD_DATA_PORT |= (1<<LCD_DATA_PIN_D4);
else LCD_DATA_PORT &= ~(1<<LCD_DATA_PIN_D4);
*/
}
static void lcd_e_toggle(void)
/* toggle Enable Pin */
{
lcd_e_high();
__delay_cycles((CtrlClockRate/1000000)*5);
lcd_e_low();
__delay_cycles((CtrlClockRate/1000000)*1);
}
static void lcd_write(u08 data, u08 rs)
{
__delay_cycles((CtrlClockRate/1000000)*
;
for (unsigned char cycle=0; cycle<2; cycle++)
{
if (cycle == 0) lcd_out_high(data);
else lcd_out_high(data << 4);
__delay_cycles((CtrlClockRate/1000000)*
;
if (rs)
lcd_data_mode();
else
lcd_cmd_mode();
lcd_e_toggle();
}
/*
lcd_out_high(data);
__delay_cycles((CtrlClockRate/1000000)*
;
if (rs)
lcd_data_mode();
else
lcd_cmd_mode();
lcd_e_toggle();
lcd_out_high(data << 4);
__delay_cycles((CtrlClockRate/1000000)*
;
if (rs)
lcd_data_mode();
else
lcd_cmd_mode();
lcd_e_toggle();
*/
}
static unsigned char lcd_waitcmd(unsigned char cmdwait)
{
__delay_cycles((CtrlClockRate/1000000)*9);
/* the display needs much longer to process a command */
if (cmdwait){
__delay_cycles((CtrlClockRate/1000)*2);
}
return (0);
}
/*
** PUBLIC FUNCTIONS
*/
void lcd_command(u08 cmd)
/* send commando <cmd> to LCD */
{
lcd_waitcmd(0);
lcd_write(cmd, 0);
lcd_waitcmd(1);
}
void lcd_gotoxy(u08 x, u08 y)
/* goto position (x,y) */
{
#if LCD_LINES==1
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x);
#endif
#if LCD_LINES==2
if (y == 0)
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x);
else
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x);
#endif
#if LCD_LINES==3
if (y == 0)
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x);
else if (y == 1)
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x);
else if (y == 2)
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE3 + x);
#endif
#if LCD_LINES==4
if (y == 0)
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x);
else if (y == 1)
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x);
else if (y == 2)
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE3 + x);
else /* y==3 */
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE4 + x);
#endif
} /* lcd_gotoxy */
void lcd_putc(char c)
/* print character at current cursor position */
{
lcd_waitcmd(0);
lcd_write((unsigned char)c, 1);
lcd_waitcmd(0);
}
void lcd_puts(const char *s)
/* print string on lcd */
{
while (*s) {
lcd_putc(*s);
s++;
}
}
void lcd_puts_p(const char __flash *progmem_s)
/* print string from program memory on lcd */
{
register char c;
while (c = (*(unsigned char __flash *)(progmem_s++))) {
lcd_putc(c);
}
}
void InitCGram(void) // инициализация области CGRAM
{
unsigned char i;
lcd_write(0x40, 0); // установка видео-адреса в области CGRAM
__delay_cycles((CtrlClockRate/1000000)*100); // попробовать еще это убрать
for(i=0;i<sizeof(SymbolCGRAM);i++)
{
lcd_write(SymbolCGRAM[i],1); // загрузка символов в CGRAM
__delay_cycles((CtrlClockRate/1000000)*100);
}
}
void lcd_init(u08 dispAttr)
/* initialize display and select type of cursor */
/* dispAttr: LCD_DISP_OFF, LCD_DISP_ON, LCD_DISP_ON_CURSOR, LCD_DISP_CURSOR_BLINK */
{
/*------ Initialize lcd to 4 bit i/o mode -------*/
lcd_data_port_out(); /* all data port bits as output */
//сделано в процедуре выше
//LCD_DDR_PORT |= (1<<LCD_RS_PIN) | (1<<LCD_E_PIN);
//LCD_RS_DDR |= (1<<LCD_RS_PIN); /* RS pin as output */
//LCD_E_DDR |= (1<<LCD_E_PIN); /* E pin as output */
//sbi(LCD_RS_PORT, LCD_RS_PIN); /* RS pin as 1 */
//sbi(LCD_E_PORT, LCD_E_PIN); /* E pin as 1 */
__delay_cycles((CtrlClockRate/1000)*15); /* wait 12ms or more after power-on */
for (unsigned char init_c=0; init_c<4; init_c++)
{
if (init_c < 3) lcd_out_high(LCD_FUNCTION_8BIT_1LINE);
else lcd_out_high(LCD_FUNCTION_4BIT_1LINE);
lcd_e_toggle();
__delay_cycles((CtrlClockRate/1000)*2);
}
/*
lcd_out_high(LCD_FUNCTION_8BIT_1LINE);
lcd_e_toggle();
__delay_cycles((CtrlClockRate/1000)*2);
lcd_out_high(LCD_FUNCTION_8BIT_1LINE);
lcd_e_toggle();
__delay_cycles((CtrlClockRate/1000)*2);
lcd_out_high(LCD_FUNCTION_8BIT_1LINE);
lcd_e_toggle();
__delay_cycles((CtrlClockRate/1000)*2);
lcd_out_high(LCD_FUNCTION_4BIT_1LINE);
lcd_e_toggle();
*/
/* set IO mode to 4bit */
// main init for 4-bit interface
//unsigned char i = 0;
//for (i = 0; i < sizeof(byte_init); i++) lcd_write(byte_init[i], 0);
/* from now the lcd only accepts 4 bit I/O, we can use lcd_command() */
lcd_command(LCD_FUNCTION_DEFAULT); /* function set: display lines */
lcd_command(LCD_DISP_OFF); /* display off */
lcd_clrscr(); /* display clear */
lcd_command(LCD_MODE_DEFAULT); /* set entry mode */
lcd_command(dispAttr); /* display/cursor control */
lcd_waitcmd(1);
InitCGram();
}
8042_sensor.rar echo_calc.rar tracker 2 main.rar
//C / C++ компилятор IAR Embedded Workbench IDE AVR 7.30.4//
#include "iotiny2313a.h"
#include <ioavr.h>
#include <intrinsics.h>
#include <stdio.h>
#include <stdlib.h>
#include "ina90.h"
#include "lcd.h"
#include "timeout.h"
#include "hardware.h"
#include "global_var.h"
#define START_DELAY 500 //милисекунд для установления режимов усилителя по постоянному току
#define ENABLE_LCD // если включено - светодиоды не используются
#define ENABLE_SOUND
#define ENABLE_USART
#define OLD_AVERAGE_FILTER // усредняющий и помехоподавляющий фильтр
#define USE_MANUAL_TIME_TX // задать время накачки вручную - для особых датчиков
#define ManualTimeTX 0x75
#define BoardV3 // на плате 3 версии находятся ускоряющие конденсаторы 470пФ и открывающий вспомогательный транзистор в драйвере полевика
#ifdef BoardV3
#define CAP_BOOST_TIME 5 // -5us
#define TIME_GUARD 0x0c // 12us
#define START_TIME_TX 64 // 100us
#else
#define CAP_BOOST_TIME 0 // 0
#define TIME_GUARD 0x0a // 10 us
#define START_TIME_TX 0x41 // 65 us
#endif
#define UTC_DELAY_1 6
#define UTC_DELAY_2 6
#define baudrate 38400 // 57600; 115200; 128000
void LowBatIndicationLoop (void);
void __watchdog_init (void)
{
//запускаю сторожевой таймер на 2 секунды
__watchdog_reset ();
WDTCR |= ((1<<WDCE)|(1<<WDE));
WDTCR = (1<<WDE)|(7<<WDP0);
__watchdog_reset ();
}
void InitTimers (void)
{
TCCR1A = 0x00;
TCCR1B |= ((1<<CS10) | (1<<WGM12));
OCR1A = 58500; //50000+6; //0xc350; //0xc350;
TCCR0B |= (4<<CS00);
TIMSK |= ((1<<TOIE0) | (1<<OCIE1A));
ACSR |= (1<<ACIC);
}
void InitPorts (void)
{
PortPot |= (1<<Pot);
PortPotDir |= (1<<Pot);
PortKeys |= ((1<<Q2) | (1<<Q0) | (1<<Q1));
PortKeysDir |= ((1<<Q2) | (1<<Q0) | (1<<Q1));
PortSpeakerDir |= (1<<Speaker);
PortSys |= ((1<<Pot) | (1<<Q2) | (1<<Q0) | (1<<Q1) | (1<<BatMeter));
PortSysDir |= ((1<<Pot) | (1<<Q2) | (1<<Q0) | (1<<Q1) | (1<<Speaker));
}
void InitUsart (unsigned int baud)
{
UBRRH = (unsigned char)(baud>>
;UBRRL = (unsigned char)baud;
UCSRB |= (1<<TXEN);
}
void USARTSendChar (unsigned char data)
{
#ifdef ENABLE_USART
while (!( UCSRA & (1<<UDRE))); // ждем, пока отправится предыдущий байт
UDR = data;
#endif //ENABLE_USART
}
void InitMode (void)
{
IntegratorCycleEnd = 0x00; // переменная глобальная, поэтому равна 0 после RESET
//устанавливаем начальные временные интервалы
TimeTX = START_TIME_TX-CAP_BOOST_TIME;
TimeGuardAfterTXOFF = 0; // переменная глобальная, поэтому равна 0 после RESET
TimeGuardAfterRXON = 0;// + CAP_BOOST_TIME;// + UTC_DELAY_1; // переменная глобальная, поэтому равна 0 после RESET
TimeIntegration = 0x10;
__enable_interrupt();
}
void GetPotPosition (void)
{
unsigned int counter = 0;
__disable_interrupt();
PortPotDir &= ~(1<<Pot); //переключаем выход на вход
PortPot &= ~(1<<Pot);
while (PinPot & (1<<Pot)) { counter += PositionAddStep; } //ждем, пока напряжение упадет до порогового
UDR = (unsigned char)counter;
PortPot |= (1<<Pot); //переключаем вход на выход
PortPotDir |= (1<<Pot);
counter -= PositionSub;
if ((counter > PositionMax) || (counter == 0)) counter = 1; // проверяем, не вылезло ли за пределы
Sensitivity = counter;
UDR = (unsigned char)Sensitivity;
}
__flash signed int segmentsDec[5]={10000,1000,100,10,1};
unsigned char String[5];
void CharToStringDec(signed int inp)
{
unsigned char i;
String[0]=String[1]=String[2]=String[3]=String[4]=0;
// перевод
for(i=0;i<5

{
if((inp-segmentsDec[i])>=0)
{
inp-=segmentsDec[i];
String[i]++;
}
else i++;
}
}
#ifdef ENABLE_LCD
static __flash char str01 [] = " -<>+ "; //+000
static __flash char str02 [] = "Wait"; //+000
void LCDBarUpdate (signed int level)
{
unsigned char col, pos;
signed int t;
if (level < 0) t = 0;
if (level < 256) t = (signed int)level;
else t = 255;
if (level >= threshold5) { ToneNumber = 5; }
else if (level >= threshold4) { ToneNumber = 4; }
else if (level >= threshold3) { ToneNumber = 3; }
else if (level >= threshold2) { ToneNumber = 2; }
else if (level >= threshold1) { ToneNumber = 1; }
else { ToneNumber = 0; }
if (++LCDPrescaler > 2)
{
LCDPrescaler = 0;
lcd_gotoxy(0,0);//здесь показать уровень
lcd_puts_p(str01);
if (level < 0) { lcd_putc('-'); }
else { lcd_putc(' '); }
CharToStringDec(level); // конвертация
for (unsigned char v=1; v<5; v++) lcd_putc(String[v]+0x30);
lcd_gotoxy(0,1);
col = (t+4
/ 16;//рассчитываем номер знакоместа для рисования палкиif (col>0) for (unsigned char z=0; z<col; z++) lcd_putc(0x05);//рисуем несколько полностью закрашенных знакомест
//рассчитываем номер символа для отображения в знакоместе //5 вариантов
pos = (t+4
- (col*16); // остатокpos = (pos)/3;
lcd_putc(pos); //0x00+
for (unsigned char t=0; t<16; t++) lcd_putc(' '); //не чистим экран, а заполняем пробелами
}
}
#endif //ENABLE_LCD
void DelayUnits (unsigned long time)
{
while (time--) {}
}
#pragma vector = TIMER1_COMPA_vect //вызывается раз в 5мс
__interrupt void KeyDrive (void)
{
unsigned int ICRData = ICR1; //получаем данные о времени срабатывания компаратора
PortKeys &= ~(1<<Q1); //выключаем первый усилитель
DelayUnits (10);
PortKeys &= ~(1<<Q0); //включаем накачку катушки
DelayUnits (TimeTX);
PortKeys |= (1<<Q0); //выключаем накачку катушки
DelayUnits (TimeGuardAfterTXOFF);
PortKeys |= (1<<Q1); //включаем первый усилитель
DelayUnits (TimeGuardAfterRXON);
PortKeys &= ~(1<<Q2); //включаем интегратор
DelayUnits (TimeIntegration);
PortKeys |= (1<<Q2); //выключаем интегратор
IntegratorCycleCount++;
Integrator += ICRData;
__enable_interrupt(); //разрешить прерывания
if (IntegratorCycleCount > 7)
{
IntegratorCycleCount = 0;
Integrator = (Integrator >> 3); // деление на 8
ReceivedSignal = (unsigned int)Integrator;
UDR = ReceivedSignal>>8;
IntegratorCycleEnd = 0xFF;
Integrator = 0;
}
GetPotPosition ();
__watchdog_reset ();
}
unsigned char SoundCycleCount;
#pragma vector=TIMER0_OVF_vect
__interrupt void Sound (void)
{
TCNT0 = 0xFE; // перезагрузить таймер
if ((ToneNumber != 0) && (SoundCycleCount == 0))
{
SoundCycleCount = 16 - ToneNumber;
#ifdef ENABLE_SOUND
if (PortSpeaker & (1<<Speaker)) PortSpeaker &= ~(1<<Speaker); // speaker toggle
else PortSpeaker |= (1<<Speaker);
#endif //ENABLE_SOUND
}
if (SoundCycleCount) SoundCycleCount--;
#ifdef ENABLE_SOUND
if (ToneNumber == 0) PortSpeaker &= ~(1<<Speaker); // не потребляем динамиком лишний ток
#endif //ENABLE_SOUND
}
void LowBatIndicationLoop (void) // отсюда никогда не выходим
{
TimeTX = 0; //Полная накачка уже ни к чему
PortSysDir &= ~(1<<Q0); //Выключаем ключ совсем - Полная накачка уже ни к чему
while (1)// батарея разряжена
{
__delay_cycles((CtrlClockRate/1000)*500);
if (ToneNumber == 1) ToneNumber =0;
else ToneNumber = 1;
}
}
int main (void)
{
signed int Ka=0, Kb=0, Kc=0, Kd=0, temp=0, tempdebug=0;
InitPorts ();
#ifdef ENABLE_LCD
lcd_init(LCD_DISP_ON);
lcd_clrscr();
lcd_gotoxy(6,0);
lcd_puts_p(str02);
#endif //ENABLE_LCD
#ifdef ENABLE_USART
InitUsart (((CtrlClockRate/16)/baudrate)-1);
#endif //ENABLE_USART
InitTimers ();
InitMode ();
__delay_cycles((CtrlClockRate/1000)*START_DELAY); // стартовая задержка
__watchdog_init ();
unsigned int tem;
for (unsigned char i=0; i<8; i++)
{
while (IntegratorCycleEnd == 0) {} // ждем пока пройдет интегрирование
EchoSumm = EchoSumm + ReceivedSignal;
tem = ReceivedSignal >> 8;
USARTSendChar ((unsigned char)tem);
USARTSendChar ((unsigned char)ReceivedSignal);
IntegratorCycleEnd = 0;
}
USARTSendChar ((unsigned char)EchoSumm);
EchoSumm = EchoSumm >> 8; // деление на 256
Echo = (unsigned char)(EchoSumm);
USARTSendChar (Echo);
Echo -= 0x32;
USARTSendChar (Echo); // эхо, полученное при калибровке
if (Echo >= 0x19) // катушка в порядке, эхо достаточной величины
{
if (Echo <= 0x37) {Ka = 0x19; Kb = 0x37; Kc = 0xA0; Kd = 0x8C; }
else if (Echo <= 0x4B) {Ka = 0x37; Kb = 0x4B; Kc = 0x8C; Kd = 0x67; }
else if (Echo <= 0x52) {Ka = 0x4B; Kb = 0x52; Kc = 0x67; Kd = 0x52; }
else if (Echo <= 0x5F) {Ka = 0x52; Kb = 0x5F; Kc = 0x52; Kd = 0x41; }
temp = Echo - Ka;
temp = temp * (Kd - Kc);
temp = Kc + (temp / (Kb - Ka));
#ifndef USE_MANUAL_TIME_TX
TimeTX = temp - CAP_BOOST_TIME; //устанавливаем рабочие тайминги
if (Echo >= 0x60) TimeTX = 0x41 - CAP_BOOST_TIME;
#endif
#ifdef USE_MANUAL_TIME_TX
TimeTX = ManualTimeTX;
#endif //USE_MANUAL_TIME_TX
TimeGuardAfterTXOFF = TIME_GUARD;
TimeGuardAfterRXON = 0x00;// + CAP_BOOST_TIME;// + UTC_DELAY_1 + UTC_DELAY_2;
TimeIntegration = 0x32;
USARTSendChar (TimeTX); // вычисленное время накачки
for (unsigned char i=0; i<10; i++) // пропускаем 10 циклов для устаканивания
{
while (IntegratorCycleEnd == 0) {} // пропускаем 1 цикл
IntegratorCycleEnd = 0;
}
while (IntegratorCycleEnd == 0) {} // пропускаем 1 цикл, этого достаточно
IntegratorCycleEnd = 0;
unsigned int tem;
EchoSumm = 0;
for (unsigned char i=0; i<32; i++)
{
while (IntegratorCycleEnd == 0) {} // ждем пока пройдет интегрирование
tem = ReceivedSignal >> 8;
USARTSendChar ((unsigned char)tem);
USARTSendChar ((unsigned char)ReceivedSignal);
EchoSumm += ReceivedSignal;
IntegratorCycleEnd = 0;
}
EchoSumm = EchoSumm >> 5; // деление на 32
BaseValue = (unsigned int)EchoSumm; // получили базовое значение при отсутствии металла
tem = BaseValue >> 8;
USARTSendChar ((unsigned char)tem);
USARTSendChar ((unsigned char)BaseValue);
USARTSendChar (BaseValue>>
; //базовое значениеwhile (1) // основной цикл обнаружения металла
{
while (IntegratorCycleEnd == 0) {} // ждем пока пройдет интегрирование
IntegratorCycleEnd = 0;
#ifdef OLD_AVERAGE_FILTER //усреднитель сигнала
EchoSumm = 0;
for (unsigned char z=0; z<(ArrayLength-1); z++) { ArrayReceivedSignal [z] = ArrayReceivedSignal [z+1]; } // сдвинули массив к 0 ячейке
ArrayReceivedSignal [ArrayLength-1] = ReceivedSignal; // в последнюю ячейку вносим свежее значение
for (unsigned char z=0; z<ArrayLength; z++) EchoSumm += ArrayReceivedSignal [z]; // суммируем последние показания
ReceivedSignal = (unsigned int)(EchoSumm / ArrayLength);
#endif //OLD_AVERAGE_FILTER
UDR = ReceivedSignal;
tem = ReceivedSignal >> 8;
USARTSendChar ((unsigned char)ReceivedSignal);
USARTSendChar ((unsigned char)tem);
temp = ReceivedSignal - BaseValue; // сравнение с опорным значением
tempdebug = temp + 127;
if (tempdebug > 255) tempdebug = 255;
if (tempdebug < 0) tempdebug = 0;
UDR = tempdebug;
temp += temp; // разницу удваиваем со знаком
temp += temp; // разницу удваиваем со знаком
temp = 250;
temp = temp / ((signed int)Sensitivity);
USARTSendChar ((unsigned char)Sensitivity);
#ifdef ENABLE_LCD // тут своя процедура вывода полосы
if (temp < -4
temp = -48; // следим за рамкамиif (temp > 999
temp = 9999;if (++LCDPrescaler > 2)
LCDPrescaler = 0;
LCDBarUpdate (temp);
#endif //ENABLE_LCD
}
}
else LowBatIndicationLoop ();
}
----------------------
/*оптимизировано для меньшего размера кода, для случая если 4 бита, RS и E находятся в пределах 1 порта*/
#include <ioavr.h>
//#include <avr/pgmspace.h>
#include "timeout.h"
#include <intrinsics.h>
#include "lcd_hw.h"
#include "lcd.h"
__flash char SymbolCGRAM[48] = {
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
0x00, /* ........ */
// символ №0
0x10, /* ...$.... */
0x10, /* ...$.... */
0x10, /* ...$.... */
0x10, /* ...$.... */
0x10, /* ...$.... */
0x10, /* ...$.... */
0x10, /* ...$.... */
0x10, /* ...$.... */
// символ №1
0x18, /* ...$$... */
0x18, /* ...$$... */
0x18, /* ...$$... */
0x18, /* ...$$... */
0x18, /* ...$$... */
0x18, /* ...$$... */
0x18, /* ...$$... */
0x18, /* ...$$... */
// символ №2
0x1C, /* ...$$$.. */
0x1C, /* ...$$$.. */
0x1C, /* ...$$$.. */
0x1C, /* ...$$$.. */
0x1C, /* ...$$$.. */
0x1C, /* ...$$$.. */
0x1C, /* ...$$$.. */
0x1C, /* ...$$$.. */
// символ №3
0x1E, /* ...$$$$. */
0x1E, /* ...$$$$. */
0x1E, /* ...$$$$. */
0x1E, /* ...$$$$. */
0x1E, /* ...$$$$. */
0x1E, /* ...$$$$. */
0x1E, /* ...$$$$. */
0x1E, /* ...$$$$. */
// символ №4
0x1F, /* ...$$$$$ */
0x1F, /* ...$$$$$ */
0x1F, /* ...$$$$$ */
0x1F, /* ...$$$$$ */
0x1F, /* ...$$$$$ */
0x1F, /* ...$$$$$ */
0x1F, /* ...$$$$$ */
0x1F, /* ...$$$$$ */
// символ №5
};
/* compatibilty macros for old style */
/*
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
*/
/*
** constants/macros
*/
void lcd_e_high(void)
{
LCD_DATA_PORT |= (1<<LCD_E_PIN);
}
void lcd_e_low(void)
{
LCD_DATA_PORT &= ~(1<<LCD_E_PIN);
}
void lcd_cmd_mode(void)
{
LCD_DATA_PORT &= ~(1<<LCD_RS_PIN); // RS=0 command mode
}
void lcd_data_mode(void)
{
LCD_DATA_PORT |= (1<<LCD_RS_PIN); // RS=1 data mode
}
void lcd_data_port_out(void)
{ /* defines all data pins as output */
LCD_DDR_PORT |= (1<<LCD_DATA_PIN_D7) | (1<<LCD_DATA_PIN_D6) | (1<<LCD_DATA_PIN_D5) | (1<<LCD_DATA_PIN_D4) | (1<<LCD_RS_PIN) | (1<<LCD_E_PIN);
//LCD_DDR_PORT |= (1<<LCD_RS_PIN) | (1<<LCD_E_PIN);
/*
LCD_DDR_PORT |= (1<<LCD_DATA_PIN_D7);
LCD_DDR_PORT |= (1<<LCD_DATA_PIN_D6);
LCD_DDR_PORT |= (1<<LCD_DATA_PIN_D5);
LCD_DDR_PORT |= (1<<LCD_DATA_PIN_D4);
*/
}
#if LCD_LINES==1
#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_1LINE
#else
#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_2LINES
#endif
/*
** function prototypes
*/
static void lcd_e_toggle(void);
static void lcd_out_high(u08 d);
//static void lcd_out_low(u08 d);
/*
** local functions
*/
/*
static void lcd_out_low(u08 d)
{ // output low nibble
if (d&0x0
LCD_DATA_PORT_D7 |= (1<<LCD_DATA_PIN_D7);else LCD_DATA_PORT_D7 &= ~(1<<LCD_DATA_PIN_D7);
if (d&0x04) LCD_DATA_PORT_D6 |= (1<<LCD_DATA_PIN_D6);
else LCD_DATA_PORT_D6 &= ~(1<<LCD_DATA_PIN_D6);
if (d&0x02) LCD_DATA_PORT_D5 |= (1<<LCD_DATA_PIN_D5);
else LCD_DATA_PORT_D5 &= ~(1<<LCD_DATA_PIN_D5);
if (d&0x01) LCD_DATA_PORT_D4 |= (1<<LCD_DATA_PIN_D4);
else LCD_DATA_PORT_D4 &= ~(1<<LCD_DATA_PIN_D4);
}
*/
static void lcd_out_high(u08 d) // output high nibble
{
unsigned char temp;
LCD_DATA_PORT &= ~((1<<LCD_DATA_PIN_D7) | (1<<LCD_DATA_PIN_D6) | (1<<LCD_DATA_PIN_D5) | (1<<LCD_DATA_PIN_D4));//сбросили DATA
temp = 0xF0 & d; // маскируем младшие биты на всякий случай
LCD_DATA_PORT |= temp;
/*
if (d&0x80) LCD_DATA_PORT |= (1<<LCD_DATA_PIN_D7);
else LCD_DATA_PORT &= ~(1<<LCD_DATA_PIN_D7);
if (d&0x40) LCD_DATA_PORT |= (1<<LCD_DATA_PIN_D6);
else LCD_DATA_PORT &= ~(1<<LCD_DATA_PIN_D6);
if (d&0x20) LCD_DATA_PORT |= (1<<LCD_DATA_PIN_D5);
else LCD_DATA_PORT &= ~(1<<LCD_DATA_PIN_D5);
if (d&0x10) LCD_DATA_PORT |= (1<<LCD_DATA_PIN_D4);
else LCD_DATA_PORT &= ~(1<<LCD_DATA_PIN_D4);
*/
}
static void lcd_e_toggle(void)
/* toggle Enable Pin */
{
lcd_e_high();
__delay_cycles((CtrlClockRate/1000000)*5);
lcd_e_low();
__delay_cycles((CtrlClockRate/1000000)*1);
}
static void lcd_write(u08 data, u08 rs)
{
__delay_cycles((CtrlClockRate/1000000)*
;for (unsigned char cycle=0; cycle<2; cycle++)
{
if (cycle == 0) lcd_out_high(data);
else lcd_out_high(data << 4);
__delay_cycles((CtrlClockRate/1000000)*
;if (rs)
lcd_data_mode();
else
lcd_cmd_mode();
lcd_e_toggle();
}
/*
lcd_out_high(data);
__delay_cycles((CtrlClockRate/1000000)*
;if (rs)
lcd_data_mode();
else
lcd_cmd_mode();
lcd_e_toggle();
lcd_out_high(data << 4);
__delay_cycles((CtrlClockRate/1000000)*
;if (rs)
lcd_data_mode();
else
lcd_cmd_mode();
lcd_e_toggle();
*/
}
static unsigned char lcd_waitcmd(unsigned char cmdwait)
{
__delay_cycles((CtrlClockRate/1000000)*9);
/* the display needs much longer to process a command */
if (cmdwait){
__delay_cycles((CtrlClockRate/1000)*2);
}
return (0);
}
/*
** PUBLIC FUNCTIONS
*/
void lcd_command(u08 cmd)
/* send commando <cmd> to LCD */
{
lcd_waitcmd(0);
lcd_write(cmd, 0);
lcd_waitcmd(1);
}
void lcd_gotoxy(u08 x, u08 y)
/* goto position (x,y) */
{
#if LCD_LINES==1
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x);
#endif
#if LCD_LINES==2
if (y == 0)
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x);
else
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x);
#endif
#if LCD_LINES==3
if (y == 0)
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x);
else if (y == 1)
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x);
else if (y == 2)
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE3 + x);
#endif
#if LCD_LINES==4
if (y == 0)
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x);
else if (y == 1)
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x);
else if (y == 2)
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE3 + x);
else /* y==3 */
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE4 + x);
#endif
} /* lcd_gotoxy */
void lcd_putc(char c)
/* print character at current cursor position */
{
lcd_waitcmd(0);
lcd_write((unsigned char)c, 1);
lcd_waitcmd(0);
}
void lcd_puts(const char *s)
/* print string on lcd */
{
while (*s) {
lcd_putc(*s);
s++;
}
}
void lcd_puts_p(const char __flash *progmem_s)
/* print string from program memory on lcd */
{
register char c;
while (c = (*(unsigned char __flash *)(progmem_s++))) {
lcd_putc(c);
}
}
void InitCGram(void) // инициализация области CGRAM
{
unsigned char i;
lcd_write(0x40, 0); // установка видео-адреса в области CGRAM
__delay_cycles((CtrlClockRate/1000000)*100); // попробовать еще это убрать
for(i=0;i<sizeof(SymbolCGRAM);i++)
{
lcd_write(SymbolCGRAM[i],1); // загрузка символов в CGRAM
__delay_cycles((CtrlClockRate/1000000)*100);
}
}
void lcd_init(u08 dispAttr)
/* initialize display and select type of cursor */
/* dispAttr: LCD_DISP_OFF, LCD_DISP_ON, LCD_DISP_ON_CURSOR, LCD_DISP_CURSOR_BLINK */
{
/*------ Initialize lcd to 4 bit i/o mode -------*/
lcd_data_port_out(); /* all data port bits as output */
//сделано в процедуре выше
//LCD_DDR_PORT |= (1<<LCD_RS_PIN) | (1<<LCD_E_PIN);
//LCD_RS_DDR |= (1<<LCD_RS_PIN); /* RS pin as output */
//LCD_E_DDR |= (1<<LCD_E_PIN); /* E pin as output */
//sbi(LCD_RS_PORT, LCD_RS_PIN); /* RS pin as 1 */
//sbi(LCD_E_PORT, LCD_E_PIN); /* E pin as 1 */
__delay_cycles((CtrlClockRate/1000)*15); /* wait 12ms or more after power-on */
for (unsigned char init_c=0; init_c<4; init_c++)
{
if (init_c < 3) lcd_out_high(LCD_FUNCTION_8BIT_1LINE);
else lcd_out_high(LCD_FUNCTION_4BIT_1LINE);
lcd_e_toggle();
__delay_cycles((CtrlClockRate/1000)*2);
}
/*
lcd_out_high(LCD_FUNCTION_8BIT_1LINE);
lcd_e_toggle();
__delay_cycles((CtrlClockRate/1000)*2);
lcd_out_high(LCD_FUNCTION_8BIT_1LINE);
lcd_e_toggle();
__delay_cycles((CtrlClockRate/1000)*2);
lcd_out_high(LCD_FUNCTION_8BIT_1LINE);
lcd_e_toggle();
__delay_cycles((CtrlClockRate/1000)*2);
lcd_out_high(LCD_FUNCTION_4BIT_1LINE);
lcd_e_toggle();
*/
/* set IO mode to 4bit */
// main init for 4-bit interface
//unsigned char i = 0;
//for (i = 0; i < sizeof(byte_init); i++) lcd_write(byte_init[i], 0);
/* from now the lcd only accepts 4 bit I/O, we can use lcd_command() */
lcd_command(LCD_FUNCTION_DEFAULT); /* function set: display lines */
lcd_command(LCD_DISP_OFF); /* display off */
lcd_clrscr(); /* display clear */
lcd_command(LCD_MODE_DEFAULT); /* set entry mode */
lcd_command(dispAttr); /* display/cursor control */
lcd_waitcmd(1);
InitCGram();
}

Comment