热度 1|||
N久没来更新了,发发去年做的一个微型打印机程序;
初步版本。。实际应用中加入了硬件忙信号检测等等。。但此版本同样经过验证。
借鉴printf()函数。。精简修改,解决了AVR C编译器自带的printf()函数太庞大的问题。。
/*------------------------------------------------------------------------------
File : Printer_WH.c
Project : Printer_WH.prj
Item : Cam Controller TT-FZ0430607-V1.0 F60608027
New Data : 2007-10-23
Author : wangxinjia
Comments : Printet -
Uart0 Link
( Uart - SIUPO(北京迅普微型打印机) )
------------------------------------------------------------------------------*/
#include "Universal.h"
//#include "Printer_WH.h"
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define BAUD 9600
#define UBRR_VALUE (INT32U)FCLK/16/(INT32U)BAUD -1
#define NUL 0x00 //空
#define BEL 0x07 //报警符
#define BS 0x08 //退格
#define HT 0x09 //横向列表
#define LF 0x0A //换行
#define VT 0x0B //垂直制表
#define FF 0x0C //换页(走纸控制)
#define CR 0x0D //回车
#define SO 0x0E //横向放大两倍(移位输出)
#define DC4 0x14 //横向无放大(设备控制4)
#define CAN 0x18 //删除一行(做废)
#define ESC 0x1B //
#define FS 0x1C //
#define SPACE 0x20 //空格
#define PANE 0X3C //方框
static char buf[25] ;
UCHAR PrintDataPrec ;
UCHAR PrintDataSignCh ;
int PrintDataWidth ;
UCHAR PrintDataFlag ;
//--------------------------------------
#define F_ALTFORM 0x01 /* alternate form, e.g. %#x */
#define F_LONG 0x02 /* long modifier, e.g. %ld */
#define F_LEFTALIGN 0x04 /* left align, e.g. %-... */
#define F_ADDSIGN 0x08 /* sign (+ or -) e.g. %+, or %(space) */
#define F_ZEROPADD 0x10 /* zero padded instead of space padded */
#define F_FRACTION 0x20 /* fraction */
//---------------------------------------
void PrinterInit(void);
void PrintLineChar(char *s);
void PrintChar(unsigned char c);
void PrintString(char *bp);
void PrintDigit(char *bp);
int MixPrintFun(CONST char *fmt, ...);
void uart0_init (void)
{
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
// UCSRC = BIT(URSEL)|BIT(UPM1)|BIT(UCSZ1)|BIT(UCSZ0); //8,even,1
UCSRC = BIT(URSEL)|BIT(UCSZ1)|BIT(UCSZ0); //8,N,1
UBRRL = WORD_LO(UBRR_VALUE); //9600-0x67;38400-0x19
UBRRH = WORD_HI(UBRR_VALUE);
// UCSRB = BIT(TXEN); //only enable send
UCSRB = BIT(RXCIE)|BIT(RXEN)|BIT(TXEN); //0x98
}
void PrinterInit (void)
{
//-----串口设置--------------
uart0_init();
//-----初始化打印机----------
putchar(ESC);
putchar('@');
//-----12*12点阵汉字----------
putchar(ESC);
putchar('8');
//----------------------------
MixPrintFun("\t产品批号: 0000%5u\n",65535);
}
/*-------------------------------
* 打印一行字符:包括汉字和字符
* 从行首开始打印
* 打印完成后自动回车换行
-------------------------------*/
void PrintLineChar (char *s)
{
puts(s);
// printf("%s\n",s);
}
void PrintChar(unsigned char c)
{
unsigned char i;
switch ((unsigned char) c) {
case '\a' :
putchar(BEL); //putchar(0x07);报警符
break;
case '\b' :
putchar(BS); //putchar(0x08);退格
break;
case '\t' :
// putchar(HT); //putchar(0x09);横向列表
for(i=0;i<4;i++){
putchar(' ');
}
break;
case '\n' :
putchar(LF); //putchar(0x0A);换行
break;
case '\f' :
putchar(FF); //putchar(0x0C);走纸控制(换页)
break;
case '\r' :
putchar(CR); //putchar(0x0D);回车
break;
default :
putchar ((unsigned char) c);
}
}
// 字符串的格式化打印
// 程序先对补0和前导以及符号位进行判断处理
// 然后输出数据,注意小数点的位置
void PrintString(char *bp)
{
UCHAR i;
if (PrintDataWidth) //指定了宽度
PrintDataWidth -= strlen(bp); //除去字符剩余的宽度
if (PrintDataWidth && (PrintDataFlag & F_ADDSIGN)) //除去数据字符的宽度里面再除去符号位
PrintDataWidth--;
if (PrintDataWidth && (PrintDataFlag & F_FRACTION)) //除去数据字符的宽度里面再除去小数点位
PrintDataWidth--;
if (PrintDataFlag & F_ZEROPADD){ //前端补0
if (PrintDataFlag & F_ADDSIGN) //sign
PrintChar(PrintDataSignCh);
if (!(PrintDataFlag & F_LEFTALIGN)){ //不要求左对齐,即指定宽度右对齐
while (PrintDataWidth > 0){
PrintChar('0');
PrintDataWidth--;
}
}
}else{
if (!(PrintDataFlag & F_LEFTALIGN)){ //不要求左对齐,即指定宽度右对齐
while (PrintDataWidth > 0){ //前端补' '
PrintChar(' ');
PrintDataWidth--;
}
}
if (PrintDataFlag & F_ADDSIGN)
PrintChar(PrintDataSignCh);
}
i=strlen(bp);
while(i){ //数据输出
if ( (i==PrintDataPrec) && (PrintDataFlag & F_FRACTION) ){
PrintChar('.'); //小数点
}
PrintChar(*bp);
bp++;
i--;
}
}
// 数据打印处理
void PrintDigit(char *bp)
{
int i;
if (PrintDataPrec){
i = strlen(buf);
if (PrintDataPrec > i) //小数点位置不能越界
PrintDataPrec = i;
}
PrintString(bp);
}
/*-------------------------------
* cntrl_string 格式化文本字符串
* va_list 不确定类型(变长参数),需要stdarg.h; va_start,va_end成对使用。
* cnt_printed_chars 返回输出的字符个数
-------------------------------*/
int MixPrintFun(CONST char *fmt, ...)
{
va_list va;
char *bp;
char *s;
unsigned char* cs;
unsigned char done;
int i;
va_start(va, fmt);
// val = _print((void (*)(char))putchar, fmt, va);
for ( ; *fmt; fmt++){ //非格式字符%
if (*fmt != '%'){
PrintChar(*fmt);
continue;
}
bp = buf;
PrintDataFlag = 0;
PrintDataWidth= 0;
PrintDataPrec = 0;
PrintDataSignCh= ' ';
++fmt;
PrintDataFlag=0;
for (done = 0; ; fmt++){ //查找格式控制字符
switch (fmt[0]){
case '#': // o/0x/0X 引导
PrintDataFlag |= F_ALTFORM;
break;
case '-': //左对齐
PrintDataFlag |= F_LEFTALIGN;
break;
case '+': //正整数前面加符号+
PrintDataFlag |= F_ADDSIGN;
PrintDataSignCh = '+';
break;
case ' ': //显示符号位
PrintDataFlag |= F_ADDSIGN;
PrintDataSignCh = ' ';
break;
case '0': //用0代替输出的空格
PrintDataFlag |= F_ZEROPADD;
break;
default:
done = 1; //格式控制字符后面的数据宽度和精度以及类型等的处理
break;
}
if (done) /* break here so fmt++ would not happen */
break;
}//for (done = 0; ; fmt++)
//获得宽度
if (isdigit (fmt[0])) { //取格式化字符指定的宽度(1 bit)
PrintDataWidth = atoi ((char *) fmt);
while (isdigit (*fmt))
fmt++;
}else if (fmt[0] == '*'){ //参数指定宽度
PrintDataWidth = va_arg(va, int);
fmt++;
}
if (fmt[0] == '.'){ //获得精度
PrintDataFlag |= F_FRACTION;
++fmt;
if (isdigit(fmt[0])){ //取格式化字符指定的精度(1 bit)
PrintDataPrec = atoi ((char *) fmt);
while (isdigit (*fmt))
fmt++;
}else if (fmt[0] == '*'){ //参数指定精度
PrintDataPrec = va_arg(va, int);
fmt++;
}
}
switch (*fmt){ //输出数据格式处理
default: //无效格式,当字符处理
PrintChar(*fmt);
break;
case 'c': //输出字符
PrintChar(va_arg (va, int) );
break;
case 's': //输出字符串
cs = va_arg(va, unsigned char *);
i = 0;
while (cs ) {
PrintChar (cs [i++]);
}
break;
case 'd': //10进制int输出
i = va_arg (va, int);
if (i < 0){
PrintDataFlag |= F_ADDSIGN;
PrintDataSignCh = '-';
i = -i;
}
itoa (bp, i, 10);
PrintDigit(bp);
break;
case 'u': //10进制无符号数输出
// break;
case 'o': //八进制数据输出
// break;
case 'x': //16进制小写输出
// break;
case 'X': //16进制大写输出
i = va_arg (va, unsigned int);
if (*fmt == 'u'){
utoa (bp, i, 10);
}else if (*fmt == 'o'){
if (PrintDataFlag & F_ALTFORM)
*bp++ = 'o';
utoa (bp, i, 8);
bp--; //'o'
}else{
if (PrintDataFlag & F_ALTFORM){
*bp++ = '0';
*bp++ = fmt[0];
}
utoa (bp, i, 16);
if (fmt[0] == 'X'){
for (s = buf; *s; s++)
*s = toupper(*s);
}
bp-=2; //0x
}
PrintDigit(bp);
break;
}//switch (*fmt)
}//for ( ; *fmt; fmt++)
va_end(va);
return 1;
}