[Из песочницы] Перепрограммируем кассу и печатаем на ней Киану Ривза

Привет, Хабр!

Как то раз была у меня «работа» — нужно было сделать управление кассовым аппаратом Штрих-ФР-К. Так как моя карьера начиналась с ремонта ККТ, торешил взяться за эту работу.

image
Так выглядит сама касса и пробное изображение моего коллеги:

image

Так же по мимо управления движками и термоголовкой в аппарате пришлось написать небольшой скрипт на питоне с использованием библиотеки OpenCV. Итак, поехали.

Все началось с изучения рем. дока. к данной кассе и последующего подключения логического анализатора на пины термоголовки. Я отправил на печать, через штриховый тест драйвер букву «С». И вот что у меня получилось:

image

По DATA значение точек (всего 432 точки в строке), SCK — cинхросигнал, STB0, STB1, STB2 — стробы для нагрева термоголовки, LATCH — защелкивание данных. Строчку вбил в сдвиговый регистр, прожег, пошел дальше.

Следующий этап был доработка платы для ускорения процесса разработки.

image

Теперь перейдем к коду.

 void go(int n, int shag)
{
	switch (shag)
	{
		case 0: 	PORTA=0b10001000; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
		case 1: 	PORTA=0b10101010; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
		case 2: 	PORTA=0b00100010; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
		case 3: 	PORTA=0b01100110; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
		case 4: 	PORTA=0b01000100; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
		case 5: 	PORTA=0b01010101; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
		case 6: 	PORTA=0b00010001; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
		case 7: 	PORTA=0b10011001; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
	}

}


Есть две схемы управления шаговым двигателем для этой кассы. 4-шаговый и 8-шаговым. Я выбрал 8, так как движки работали лучше.

#define DATA 2
#define SCK 1
#define LATCH 3
#define STB0 2
#define STB1 3
#define STB2 4
#define DATA_IN PORTB
#define STB_IN PORTE

int sck()
{
	_delay_us(3);
	DATA_IN|= (1<0)
		{
			DATA_IN|=(1<


Код отправки данных в термоголовку. Термоголовка работает как сдвиговый регистр. Как она работает я писал выше.

void print_all_pixel()
{
	while(n<55)
	{
		print_stroka(str[n]);
		_delay_us(3);
		n++;
	}
	latch();
	n=0;
	STB_IN&=0b11111011;
	_delay_us(500);
	STB_IN|=(1<


Функция печати и прожига строк.

void recieve()
{
///while(f);
	if ((com==0x50)&&(rezhim==0))/// P
	{
	//USART_Transmit('P');
		com=0;

		rezhim=1;

	}

	if ((rezhim==1)&&(com!=0))
	{
		//USART_Transmit('P');
		str[iFF]=com;
		com=0;
		iFF++;

		if (iFF==54)
		{
		print_all_pixel();
						
				rezhim=0;
				iFF=0;
				 
			USART_Transmit('P');
			USART_Transmit('R');
			USART_Transmit('I');
			USART_Transmit('N');
			USART_Transmit('T');
			USART_Transmit('E');
			USART_Transmit('D');



		}

	}
	if ((com==0x52)&&(rezhim==0))///R
	{
	com=0;
	promotka();
	USART_Transmit('O');
	USART_Transmit('K');
	//vpered(300);
	}
}


Основная функция, которая крутится в вечном вайле. Когда приходит буква «P» я включаю вход в режим печати. Далее все остальные символы начинают набиваться в буфер. Далее когда буфер набивается 54 байтами (или 432 бита), то печатаем строку и отправляем по УСАРТ слово PRINTED.
Ну вот и все с железной частью. В следующей части я распишу про программную часть, а именно про программу на питоне. Исходники.

image

© Habrahabr.ru