Цитата(Graf83 @ Apr 6 2011, 12:17)

переменная типа int или char, интерфейс lpt (cetronics) пишу на си
чип atmega162
Вот Вам готовый код, выкусил из старого проекта (печатался протокол измерений, работает у людей до сих пор

).
Собиралось на меге16, компилятор GCC (WinAVR). Хотите под CV - портируйте.
Особенности:
-использует аппаратные прерывания для сигналов BUSY и ACK.
-циклический буфер (FIFO)
Не забудьте линию SELECT_IN подключить к 0, и линию AUTO_FEED к питанию (лог 1)
Рекомендую подключить линии принтера через резисторы 50-100 ом.
Если линии прерывания заняты под другие цели, то можно и без них обойтись - уберите #define USE_INTERRUPTS и в каком - либо цикле или в таймере запускайте периодически LPT_BSR()
Печатать можно (как Вы уже заметили в main()) обычным printf() все, что пожелаете

Или используйте LPT_putc() напрямую, если нужно.
CODE
#include <avr/io.h>
#include <string.h>
#include <stdio.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#define USE_INTERRUPTS
#define DATA_PORT PORTC // DO..D7 принтера
#define DATA_DDR DDRC
#define STATE_PORT PORTD // линии управления принтера
#define STATE_PIN PIND
#define STATE_DDR DDRD
#define BUSY_PIN 2 //INT0
#define ACK_PIN 3 //INT1
#define PAPER_OUT_PIN 4
#define ERROR_PIN 5
#define INIT_PIN 6
#define STROBE_PIN 7
#ifndef BUFFER_SIZE
#define BUFFER_SIZE 32
#endif
#define BUFFER_MASK ( BUFFER_SIZE - 1)
#if ( BUFFER_SIZE & BUFFER_MASK )
#error Buffer size is not a power of 2
#endif
volatile uint8_t Buf[BUFFER_SIZE];
volatile uint8_t Head;
volatile uint8_t Tail;
volatile uint8_t printer_state = 0;
void LPT_init(void)
{
DATA_DDR = 0xFF;
STATE_PORT |= (1<<INIT_PIN) | (1<<STROBE_PIN);
STATE_DDR |= (1<<INIT_PIN) | (1<<STROBE_PIN); //Output pins
STATE_DDR &= ~((1<<BUSY_PIN) | (1<<ACK_PIN) | (1<<PAPER_OUT_PIN) | (1<<ERROR_PIN)); //Input pins
Head = 0;
Tail = 0;
#ifdef USE_INTERRUPTS
MCUCR = (1<<ISC01) | (1<ISC11); //interrupts on falling edge
GICR |= (1<<INT0) | (1<<INT1);
sei();
#endif
}
void init_printer(void)
{
STATE_PORT &= ~(1<<INIT_PIN);
_delay_us(5);
STATE_PORT &= ~(1<<INIT_PIN);
_delay_us(100);
}
uint8_t LPT_state(void)
{
uint8_t state = 0;
if(STATE_PIN & (1<<BUSY_PIN)) state |= 1; //Printer busy
if(STATE_PIN & (1<<PAPER_OUT_PIN)) state |= 2; //Paper out
if(!(STATE_PIN & (1<<ERROR_PIN))) state |= 4; //Internal printer error
return state;
}
uint8_t LPT_transmit(void)
{
uint8_t tmp;
if(Head == Tail) return 0; //Buffer empty, nothing to send
printer_state = LPT_state(); if(printer_state) return printer_state; // printer not redy
tmp = (Tail + 1) & BUFFER_MASK; // calculate and store new buffer index
Tail = tmp;
DATA_PORT = Buf[tmp]; // get one byte from buffer and write it to out port
// do STROBE pulse
_delay_us(1);
STATE_PORT &= ~(1<<STROBE_PIN);
_delay_us(1);
STATE_PORT |= (1<<STROBE_PIN);
_delay_us(1);
return 0; //succes
}
void LPT_BSR(void)
{
do
{
printer_state = LPT_transmit();
} while((printer_state==0)&&(Head!=Tail)); //try transmission
}
#ifdef USE_INTERRUPTS
ISR(INT0_vect)
{
//Busy signal go down, wakeup
LPT_BSR();
}
ISR(INT1_vect)
{
//ACK signal arrived
LPT_BSR();
}
#endif
void LPT_putc(unsigned char data)
{
uint8_t tmp;
tmp = (Head + 1) & BUFFER_MASK;
while ( tmp == Tail ){
;// wait for free space in buffer
}
Buf[tmp] = data;
Head = tmp;
LPT_BSR();
}
static int lpt_putchar(char c, FILE *stream)
{
if (c == '\n') LPT_putc('\r'); // insert CR before LF
LPT_putc(с);
return 0;
}
FILE lptf = FDEV_SETUP_STREAM(lpt_putchar, NULL, _FDEV_SETUP_WRITE);
int main( void )
{
int test_value = 315;
LPT_init(); // driver init
init_printer(); // необязательно
_delay_ms(1000); // для некоторых старых принтеров может потребоваться задержка после сброса и больше (2-3 секунды), если что, подправьте
stdout = &lptf; // назначаем STDOUT на принтер
printf("Hello printer!\n");
printf("Value = %d\n", test_value);
return 0;
}
PS: Если чео неясно - спрашивайте.