EDA365电子论坛网

标题: lpc1114热敏打印机源程序 [打印本页]

作者: Diabloa    时间: 2018-10-31 11:11
标题: lpc1114热敏打印机源程序
lpc1114热敏打印机源程序
3 ]  Q5 A5 l( ~9 g

$ \" ]1 J$ k4 w//本文件主要定义可程序的入口函数main, main函数里主要对系统、参数、硬件接口进新初始化,之后等待读取串口数据
, c& q9 F/ h* K: C#include <stdio.h>9 {/ m, p2 m$ \: w3 o* ^# X( V- J
#include <stdlib.h>
2 S' d4 L0 |$ C% D* U#include <string.h>  s" l8 b3 H$ U4 u+ ^' z5 |
#include "LPC11xx.h" /* LPC11xx definitions */
, l; \, X( `. C% L" h, Z7 j#include "uart.h"  4 `1 q( z! x+ N- j  w
#include "timer32.h"
# `! u% `7 D# a: ~( G+ h# K#include"aw_print.h" 6 d9 @1 \6 a  F7 k
#include"aw_init_printHead.h". i$ X: _6 C$ q% A% Y; Z
#include "aw_config.h"
4 s# Q! R5 P5 K& Z#include "aw_font.h", \! u  B; R. _: D
#include"aw_key_led.h"
% D; L6 k: Y$ G#include "user.h"! t" \% D. k. |! a  ?
#include"aw_char_app.h"
( t  s, ^* a% Q, h#include"aw_graph_app.h") J' B/ e6 A2 Z3 l  @2 [
#include"aw_barcode_app.h"
1 e1 V. h  {3 B#include "aw_command.h"
2 @7 h! I; n: Y$ h#include "pmu.h"$ X# x6 V5 J, C) l& N0 Q& f
//初始化系统中的部分全局变量0 m" k" C6 T( m, s7 ]4 j) ^
void init_Global_Variables(void): b- U' U* `& j
{& l5 n7 \: \. K: _5 z9 O" u
        current_char_index=0;
6 ?6 C- U0 }; L) j  i% o" e4 |  d% D        DealBuffer_counter=0;/ H9 h# z2 a# W3 J
        memset((low_power_t *)&low_power_Paramter,0,sizeof(low_power_t));
8 j/ X4 S1 `2 c3 U' z& G; l* d        memset((printer_work_Parameter_t *)&printer_work_Parameter,0,sizeof(printer_work_Parameter_t));& X# h2 H2 C1 V7 r
        printer_work_Parameter.printer_work_model=PRINTER_IDLE;' j: F  |: }- q! g$ `: L
        feed_dot_step=0;
* {& o# L( U& t- U; B        paper_out_flag=0;
2 b# {0 S$ z' h- G8 ^/ a        head_up_flag=0;
0 M/ K/ ^3 R- U5 R0 U  j        clear_buffer();
6 v" I  [2 y/ l' B  Q        memset((Key_IRQ_Parameter *)key_IRQ_Parameter,0,KEY_NUM*sizeof(Key_IRQ_Parameter));
* _" f4 t. l4 a0 I}" N) O$ O9 P5 I# i+ {3 }+ y8 P6 r
int main(void)
9 M; S2 f9 m# a# d$ ^% h8 V' D{
0 f4 L1 K" T6 m7 F2 H        #if UART_DEBUG2 c7 a6 L4 l- W; f
        char buffer[1024];3 ?$ W6 }. w: x
        uint32_t counter,timer;+ i" C& j+ e2 e5 a& j6 A7 t5 |* r( i
        SystemInit();: b$ v" x* _& m
        Init_Sys_Parameter();
( }9 B8 S( }, e3 D% {        init_Global_Varibles();
" ^% \. o! G! G6 \6 t. c+ i        UARTInit(sys_Parameter.uart_para.baudrate);! Y: n) S& [9 r7 n% M( Y
        #ifdef PROJECT_DEBUG8 U; s$ c1 c! E/ t0 ^  m  M! M6 p3 r
        printf("\n\r-- Printer_Project V1.0 --\n\r");
8 \8 ^* B: `8 m        printf("\n\r-- Serial Communication test  --\n\r");9 U( P+ r. d* @0 V  S3 |3 S8 d4 L+ b
        #endif9 ^; ]4 L3 I0 z) O& d7 e( w
        counter=0;
, E+ y2 j2 }% P; }# ^$ z6 ^: H, j        timer=0;2 v$ g: {  x+ X/ E5 X
        memset(buffer,0,1024);+ \* W6 {+ a/ ^3 }, g/ t1 c) j& Y, Q$ i
        while(1)4 [/ Z& @1 B# K! Q
        {
, Z+ o* A1 c4 ]3 ?- m# g% k- _                if(UartBuffer_read()==1)
! C0 ?! T* A6 X0 i* O                {5 X1 L! k2 l0 z$ V
                        timer=0;memcpy(buffer+counter,&DealBuffer,DealBuffer_counter);5 x: D+ c" [  T1 j2 ]# V. c. T  `
                        counter+=DealBuffer_counter;
5 r2 Q, A6 ]6 F, C* {}
7 h& k! Z: }7 k. ~else
$ z" H/ \; V* t5 ?6 p{5 b( k4 F* r( h9 d
        if(timer<10)
( V* w* i+ ~. i* s7 ?% H) a        {
" k2 v, x4 s  Y. i( P                timer++;
0 \3 M, s" b" }: R! h9 w' V}! O" M) \5 ^  [0 M* o
else if(timer==10)
8 \$ ]9 r! z5 i  u  H2 O& C5 |{& B& B1 Q$ S! ^- ]
        if(counter!=0)/ j5 p2 A+ f: n) u, c* F
        {" ^1 ~$ U  E2 F  z; f, T# Q, k  q
                #ifdef PROJECT_DEBUG) D4 x8 N$ ~! H  g; S0 j1 C
                printf("%s",buffer);$ i% `5 ~9 h+ h$ W9 l/ i, u+ k1 C
                #endif
7 e9 A' T7 L5 r$ Z5 _! ~                counter=0;, M, D  Y. z7 [
                memset(buffer,0,1024);$ A) F1 Q5 |5 i( n" ~# n( ~) {
                timer=11;& E6 y! b' c$ r2 W. y
}$ m1 B; b/ w: v
}( B4 v9 X' V  h  b, c
}
) X2 K3 A' e) E: @#elif SPIFLASH_DEBUG2 a. V/ \0 z& `( ?# l
uint32_t BaseAdd;
% h! h" Q; B0 huint32_t Address;! }8 _) ]  ]7 m/ c7 u$ z- R
uint8_t MSB=0xce,LSB=0xa1;; c4 S6 e7 _% z5 }9 K; g
uint8_t dot[118];
0 [3 S1 w8 f9 Q5 G2 A3 B3 R# zSystemInit();
5 F) h; g- M% ?- I, I% I6 tspi_flash_init();;# F) H' B, w4 N5 H
while(1)6 W( j3 i$ l2 u
{
" }& |' A8 W1 c/ d6 A        BaseAdd=BASEADD_GB2312_11X12;, z' d" M. O' v% O
        if(MSB>=0xA1&&MSB<=0Xa9&&LSB>=0xA1)3 g6 ~; A) V0 N& L5 s3 f& a
        {% y) N4 X. R: s% T
                Address=((MSB-0xA1)*94+(LSB-0xA1))*24+BaseAdd;
! J! Y4 _& \/ T: V  Y0 @}
, }1 u# D1 G- delse if(MSB>=0xB0&&MSB<=0xF7&&LSB>=0xA1)
& k$ D* z! }: |8 e! u& M, V" n{/ X) N( I% ~. ^% C; m
        Address=((MSB-0xA1)*94+(LSB-0xA1)+846)*24+BaseAdd;. c4 O$ |; Q2 e0 I! Y- c* d
}
6 Z; E. D) x% a  g( ^read_spi_flash(Address,&dot[0],118);          /*取点阵*/
( B& B% A( I, O* m3 X5 Y/ `LSB++;/ D. a, @0 w& U4 P2 D
}) r9 C* K4 j  N/ {  a+ ]
#elif PRINTER_HEAD_DEBUG
( E  r* m6 H' {0 T3 @int i,keyval,keyval_bak;
/ Y) M$ _, u/ ^$ G6 i6 Zuint32_t j;
4 A& r7 O* `; ^2 s# i5 RSystemInit();/ L$ G) H; b2 T2 H" J
Init_Sys_Parameter();/ F& g* g2 I; r8 q; Z
init_Global_Variables();2 _) |3 N1 O3 d: n
init_Printer_port();
# e2 o) U+ w5 Yinit_key();                          /*4、按键初始化*/
9 X4 S! M! Y' r% ~6 [' I0 {while(1)
4 D4 h, D2 p' J7 C9 h- E1 c! E{: f, _8 `3 \6 \( I! B
        
# R+ k5 g9 s; D/ ~% M2 E) @" f}
9 W9 B3 ^- Q- T, ^( h; K#elif TIMER_TEST
: A- s; e4 c/ g" e+ Iuint16_t time;
9 E& Y' j5 U4 w5 xuint8_t i;7 k- n. v9 L6 k+ t
SystemInit();3 }: t) W7 \1 A
Init_Sys_Parameter();0 M# N' w7 y) q" V
init_Global_Variables();6 h' z3 @" D' U8 D7 P
UARTInit(115200);! l' o7 e" G; E/ [1 t  @
common_timer(1,1000);
) l9 H6 d9 t# X" O* L0 fwhile(1);
$ O* O0 M- Y6 D  J#else5 W" W" J- R( _& y) M1 h5 H" r+ D
uint32_t timer=0;                          /*用于记录连续读不到串口数据的次数*/
) N7 r. F7 T" Q1 iuint16_t get_dot_count;
/ s1 U  z5 h/ O; v' P  Zuint16_t effective_dot,num;                /*可以用于打印的点的个数*/
9 x' Y6 O( |- C5 oSystemInit();1 S0 w1 b# K$ {# S/ G1 [- e2 g
Init_Sys_Parameter();! E# r2 S& E( d5 R. t3 h
Init_project_Parameter();
$ h  k! N+ C! Pinit_Global_Variables();) H3 `" m  A1 P+ s" Z
UARTInit(sys_Parameter.uart_para.baudrate);   /*1、数据终端通讯串口初始化*/
3 k8 H% N# I% v: \8 L: _init_Printer_port();                         /*2、热敏打印头接口初始化         */' H! r, ]! r8 ~
spi_flash_init();                           /*3、字库芯片通讯初始化         */3 N0 a' W0 [) E: ?- P
init_key();                                /*4、按键led 初始化*/
' j# G$ i4 r; Q2 C9 ]$ iinit_led();- n  A* g* K- X% B* A# E
common_timer(1,COMMON_TIME);              /*启动公共定时器*/ : n8 v' h* {: e
for(timer=0;timer<0xf000;timer++)         //延时,保证先前的初始化起作用
/ W5 O  r9 T1 Y# O8 _' n1 P{
. d4 w, |$ G+ s0 c        ;  t  B6 Y; Y) h" f$ Q3 e) B2 w
}
) m" x7 j4 X' l; f3 minit_cutter_position();   /*让切纸刀回到 限位开关的位置 */
* e1 k" a+ }1 O' F4 _: x* @0 nmotor_driver_step40();    /*让电机先反正转40        步*/        . ?3 c# n9 _" F$ E& y
Hardware_flow_control(UART_FREE);  /*初始化结束,允许串口接收数据*/
6 w- Z, ~% A0 U9 {9 p/ \  n2 ]" ltimer=0;6 @* c2 F. ?: G. O, U  C' B$ V
while(1)
2 Z: k$ k  m' @) D{' Y& q+ P2 F/ S  |2 L2 `+ |" U5 @
        current_char_index=0;8 I' o2 C9 j0 m; J3 v" Q4 D
        if(UartBuffer_read()==1)  /*读取串口数据*/
  x/ @" z- N  O. h; k        {0 i, f/ {8 a  W6 R: g
                timer=0;    /*串口有数据时,将此计数器复位*/
2 i  B: K" X: e  F) Z7 d1 v                while(current_char_index<DealBuffer_counter)
: x, {* l' r% K( h: z0 [( o                {
& }- b0 Y; I: ~. w+ t1 E! Z                        switch(project_Parameter.print_type)  /*处理串口读出的数据*/                        
0 q( p3 N# \# ?0 H; m& s2 o& x" H- x: p                        {
$ P0 p# a1 o0 G, R/ R: x! t5 l- z                                case DATA_TYPE_CHAR_COMMAND:   /*字符或、命令*/
  I6 ~/ @1 i* `) A                                        if(determine_data_command((uint8_t *)(DealBuffer+current_char_index))==0)- I4 {3 i# O& e! C
                                        {" X: b2 A1 e; Z) J/ [/ H1 J
                                                if(Save_char()==0)
% |# B0 G, |& \0 F                                                {
) c( q1 x0 X0 U0 b                                                        continue;, ?' X. S  D8 R% g" k0 t. j" y
}
9 \' D& a# M# `# P5 Vif(printer_work_Parameter.printer_work_model==PRINTER_IDLE)  /*空闲*/* S9 H" |% J/ }7 h. v+ {
{: H3 o$ e0 v! a
        if(calculate_get_char_num(&num,&get_dot_count)==1)  /*有一行数据需要打印*/
% ]3 @( C" s6 ?$ v) n# ]$ |4 ]6 v        {" T* ~' {9 d2 K5 n/ l& v( P
                start_print(PRINT_CHAR);7 @* H5 ?5 y& n' b7 u
}
0 ~5 w% L# c7 c6 x}
0 b$ z3 M5 H; v9 o8 A}8 O" [; u+ b6 ?5 w7 h: X: d
else  /*命令处理*/
8 r: ?6 ]; L! t# q1 G{
  L5 k2 s, m( h" [9 V1 c7 S        command_deal((uint8_t *)DealBuffer);
4 x* W+ Q- l/ _& x8 Y9 e}
5 F) c, l/ O6 ~8 rbreak;9 s! {  E0 B; D$ {% ]
#ifdef VERTICAL_GRAPH
- x; n$ K$ _4 _: \case DATA_TYPE_VERTICAL_GRAPH:           /*垂直取模图形*/
; t0 k, s7 r, t5 E( t! H* x" D% c3 t        if(save_graph()==DATA_ENOUGH)   /*数据取完,恢复默认数据类型*/! Q6 ?$ f' Z" V. I% l
        {6 W3 k6 J1 l; C/ J( O
                project_Parameter.print_type=DATA_TYPE_CHAR_COMMAND;
6 R& V1 m9 e3 U5 F) q1 _}
0 U* V' R- z+ t& E8 [! j  Bbreak;6 {4 g- E4 E8 J& M
#endif
" x$ d) e# l- N( I' Y9 D$ W/ ^& S) ccase DATA_TYPE_HORIZONTAL_GRAPH:  /*水平取模图形*/
/ d" @5 ~& Z  c6 w  ]        if(save_graph()==DATA_ENOUGH)  /*数据取完*/- V: R7 h! e7 b. F- K, O& ]. i& Y
        {
0 L" M! d) |* N- L# |: `. m- \                graph_data.data_finish=1;
  k0 B1 M# y# t# h8 H                project_Parameter.print_type=DATA_TYPE_CHAR_COMMAND;, P; J9 Y2 K! M6 o3 m4 ^0 ^
}   /*空闲时,并且有一行以上的数据需要打印*/
% u  l& ], c7 Gif((printer_work_Parameter.printer_work_model==PRINTER_IDLE)&&(graph_data.buffer_counter/graph_data.horizontal_mode.horizontal_byteCount>0))0 L: b7 c: `  {3 T
{( V9 ]9 A0 V- W& J* \3 m
        start_print(PRINT_HORIZONTAL_GRAPH);5 ^- V. ~( a! b  B
}9 j& O+ H; y6 L8 U' q1 k+ K
else if((printer_work_Parameter.printer_pause==1)&&(printer_work_Parameter.printer_work_model==PRINT_HORIZONTAL_GRAPH))
! L( F5 u7 X  v! J3 Z5 Y9 O) m{     /*从暂停状态恢复打印*/    /*        数据接收结束*/! Q; \2 l+ y. N3 a0 K
        if((graph_data.data_finish==1)||((graph_data.buffer_counter-graph_data.printed_byteCount)/graph_data.horizontal_mode.horizontal_byteCount>0))
2 _# t' ~. n4 A        {     /*还有至少一整行数据*/
: N9 N0 Q0 v0 q9 J& [) g/ M                Resume_Print_from_pause(printer_work_Parameter.printer_work_model);, f3 r( G. g4 Z+ g
}5 e2 o4 a9 p& Q+ x2 Y6 u
}2 a9 \9 R  e- E8 M; ?4 v& M
else if((graph_data.data_finish==1)&&(printer_work_Parameter.printer_work_model!=PRINT_HORIZONTAL_GRAPH))* p8 t0 S' B' A! a. A
{      /*图片数据接收完,并且打印机还在做别的工作, 取消本次图片打印*/
/ @* n8 R! C. e5 C/ V" j( q        memset((graph_data_t *)&graph_data,0,sizeof(graph_data_t));7 {1 }3 j  d+ S1 s: u: ]- o
}
! u7 o- N; f; k' P' m1 Y! j* `break;
5 v8 }1 w/ M0 p( E1 W2 ]2 i: a1 d//case DATA_TYPE_BARCODE:  /*条形码图形*/1 q- _2 i8 ?- I6 X. p( B
//        num=save_barcode((uint8_t *)(DealBuffer+current_char_index));
0 ^4 \' ]6 v; K7 K//if(num==DATA_ENOUGH)
0 y( {* f8 F; M( E7 B//{7 l9 `6 ?( m- e; h1 V4 h- i
//        save_barcode_parity_bit();  /*数据取完开始打印*/8 f- m0 c& e$ A8 q
//        while(printer_work_Parameter.printer_work_model!=PRINTER_IDLE)" }; q0 J- t8 I" d7 h) N
//        {: U+ {0 {8 N. b9 ^! [
        //        ;
( e& {, @& h+ {# b; b9 t//}   /*条形码超出打印范围不打印*/3 A9 f3 e- b. c
//if(project_Parameter.cursor_position==0)  /*本行还是空的*/$ ^! ]8 ?+ ^6 c; O/ q% a7 a9 r; Z' B
//{
+ Q  S$ C) Q: k4 }2 l6 l/ s//        effective_dot=MAX_DOT_PERLINE-project_Parameter.print_position-project_Parameter.Limited_width_left_para-project_Parameter.Limited_width_right_para;  v) \6 G+ J/ P7 ?7 X$ R+ X2 s
//}1 {$ K- z, f) h& m$ S) f
//else* i# u# J. W1 T7 Z9 m9 T9 z$ F
//{
' D2 z; r% r$ r/ b8 f//        effective_dot=MAX_DOT_PERLINE-project_Parameter.Limited_width_right_para-project_Parameter.cursor_position;- O) g3 ~2 |, r* Q5 P) I9 T5 N
//}% ~/ |8 K5 p% L/ W5 C! D
//if(get_barcode_dot_width()<=effective_dot)
  V! q! H1 g' _7 X4 ]: _//{
+ _) F% ~  n, S* J//        start_print(PRINT_BARCODE);
+ d( S$ p7 l2 J//}
  B1 ~1 h' m7 E2 p, z$ c0 E//else, G. @7 w. |5 j7 O' q) @
//{3 j8 l  x& Z2 I) \, ^3 E
//        memset((barcode_data_t *)&barcode_data,0,sizeof(barcode_data_t));  a) I" f; [( W) S: X
//}! G% L* w6 T/ N7 ~7 B2 z9 I
//project_Parameter.print_type=DATA_TYPE_CHAR_COMMAND;4 {4 r/ z& L) [  v9 [- ?2 Q
//}
8 Y6 M5 A+ Y; j, y8 q8 s- W//else if(num==DATA_ERROR)   /*条码数据出错*/, v' m2 R' W" N* r% N* D
//{0 \' I4 F' Z) Q  @2 }
//        goto barcode_error;, Z* G/ j9 L0 R3 N
//}
  m" M1 ?( \- m( U# a//current_char_index++;$ ~1 Y' \  j; m8 t& j: J& B
//break;) m: B+ C) ]  @0 a9 _6 L
}  _( h' `$ `) n2 s/ ~
}0 i! k$ M- x# Z
}
# b  V% K. G0 ^# t6 A  ~else  /*串口中无数据*/
: R8 V2 @. O: W/ G7 A' J8 `0 T{
) z9 C: R. i8 Q* B1 V        if(timer<5)
2 O* H: A. Y' i& K; x        {
0 c5 t4 T) m2 r                timer++;* V! v) p! ?* j3 m# {
                continue;- G5 G- H1 C- K4 ^5 W* b( u
}
, ^6 z8 Q" w6 U6 H9 `' E7 Nswitch(project_Parameter.print_type)
* F+ ]7 }2 R; T{9 X+ i1 X  @9 c1 ~- _
        case DATA_TYPE_CHAR_COMMAND:     + A3 z$ F9 i/ O2 R. R
                if((printer_work_Parameter.printer_work_model==PRINTER_IDLE)&&(char_data.printed_byteCount<char_data.buffer_counter))
: ^3 l- H6 S7 p/ ~                {     /*空闲时,并且还有数据*/  O7 [& G5 U' j9 r5 B7 G8 B
                        start_print(PRINT_CHAR);2 P# p  d: q# D$ c% g- ^
}
* K; m1 Y8 K5 t; [break;
3 J3 g7 ]% m, w" N% c$ u; |' u#ifdef VERTICAL_GRAPH0 k$ r. W# s; J' {
case DATA_TYPE_VERTICAL_GRAPH:           /*垂直取模图形*/
$ y) l9 c$ T) f* u# B+ s        project_Parameter.print_type=DATA_TYPE_CHAR_COMMAND;  /*丢弃原来的数据*/
' X* k& }, o6 I: H3 ~memset((graph_data_t *)&graph_data,0,sizeof(graph_data_t));7 U( g2 s, L$ v* h  a
break;
3 p! S3 L9 ^0 H( k  a  e8 ~#endif7 z1 E# U8 a3 m1 u5 R5 v, v
case DATA_TYPE_HORIZONTAL_GRAPH:
* T# ^% f. ~. k4 U+ ~6 i, y) ?; k" U        project_Parameter.print_type=DATA_TYPE_CHAR_COMMAND;   /*三次读不到数据,认为结束*/
5 T7 [) a5 E- n  \- Cgraph_data.data_finish=1;' p8 \* I" r8 p$ O  {" H  L) x5 S2 \
if((printer_work_Parameter.printer_pause==1)&&(printer_work_Parameter.printer_work_model==PRINT_HORIZONTAL_GRAPH))  /*图片打印过程中暂停*/
- l9 R& r6 a. F; I, Q{4 K5 w! x& \! M) U" n8 U
        Resume_Print_from_pause(printer_work_Parameter.printer_work_model);2 Y) n# @  s5 G9 Y! b# Y
}7 l: F/ D% k# ]& x; ~$ e3 i
break;
' K" o2 s. O( |3 c6 Ycase DATA_TYPE_BARCODE:
8 o7 x+ w2 u) q9 n        barcode_error:7 t" k! {1 p3 a' E
project_Parameter.print_type=DATA_TYPE_CHAR_COMMAND;5 n# j; _. T6 n
memset((barcode_data_t *)&barcode_data,0,sizeof(barcode_data_t));2 o; o4 d9 R7 J( {' k
break;
* _. R1 y7 _7 a  @6 e3 E2 Qdefault:
2 {. z8 t2 b+ V2 K        break;& p9 O5 p6 W1 V
}/ p: c3 m; @& }( k1 u2 e
}
% T: g: \# w  n, I, C}  x5 k7 x8 g: F: ]' A" T/ c
#endif
! J% e' V8 y* A: Z' h9 T}7 J5 K5 H$ U" L/ `8 |8 T- T) W9 ^) ]9 Z

" x4 m9 H; Z: v4 _; r# ?  P0 g$ h* Q6 v& v

作者: 夏天的向日葵    时间: 2018-11-2 16:57
谢谢分享
作者: jodan3988    时间: 2020-7-21 18:06
本帖最后由 jodan3988 于 2020-7-21 18:40 编辑   j% E3 H2 W3 t! _; U1 Y
/ m% Y" I# t3 ]. d( N8 y
谢谢分享,赶紧学习一下,编译不通过,缺少文件,一堆error,
作者: foric    时间: 2022-1-28 23:01
这个是官网的哪个示例吗?* }! d2 Q. L  O- R2 k

作者: unrelated    时间: 2022-1-30 20:13
, z2 Z& y! z$ z) G  a/ H# Q
这个是官网的哪个示例吗?1 V0 u6
作者: Dc202312175h    时间: 2024-1-13 14:06
谢谢,加了干扰码




欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/) Powered by Discuz! X3.2