一、说明:
1、添加新文件:
在..\plutommi\mmi\TicketApp\TicketAppSrc\下添加文件CosUart.c
2、将新添加的文件加入到工程中:
在文件..\make\plutommi\mmi_app中添加如下文件信息plutommi\mmi\TicketApp\TicketAppSrc\CosUart.c。
3、用到的头文件
#include "uart_sw.h"
#include "uart_hw.h"
4、程序说明:
MTK的串口在接收数据时需要设置一个钩子函数(串口响应函数),在串口收到数据时会发送一个消息MSG_ID_UART_READY_TO_READ_IND给mmi层,mmi截获该消息后才能调用钩子函数去读串口缓存里的数据;
1、 串口初始化void CosUartInit(void)
(1)在初始化uart1时加了奇校验;
(2)去掉了软件流控:调试MTK uart1时总是不停地打印0x11 0x13,且向uart1发送0x11、0x13时,串口也收不到该数据,这是串口配置时的流控造成的,解决发法是:在uart.c中的函数void U_SetDCBConfig()中将对串口uart的流控配置去掉就可以了(代码2226行到2301行用#if 0 #endif 屏掉)。
2、接收函数U8 CosWrite(U8 *buf, U16 buflen, UART_PORT port, module_type ownerid)与
U16 CosRead(U8 *buf, U16 maxlen, UART_PORT port, module_type ownerid)
这两个读取uart1的函数作用和效果相同,用哪个都可以。
参数说明:
Buf为接收数组;
Buflen为读取的字节数;
Port串口号,此处为uart1;
Ownerid串口模式;
3、发送函数:U8 CosWrite(U8 *buf, U16 buflen, UART_PORT port, module_type ownerid)
参数说明:
Buf为接收数组;
Buflen为读取的字节数;
Port串口号,此处为uart1;
Ownerid串口模式;
4、离开对串口的控制void exit_uart(void)
二、遇到的问题
测试过程1:
1、MTK发送指令0x05 0x00 0x00 0x00给卡证,卡证回复0xcc;
2、MTK收到0xcc(串口发送消息MSG_ID_UART_READY_TO_READ_IND通知MTK从缓存中取出)后发送明文02 00 10 00 + 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11共132个字节给卡证,卡证回复密文02 00 11 00 + 50 3E D9 84 1A 65 5B AE DE 8F A1 35 73 3A 47 F5 D7 6D DC 90 C4 53 39 0B 1B C0 48 81 57 CD 09 B7 BC F2 6D 94 07 A1 2B 80 C7 58 75 47 70 75 60 30 2D 72 AB A0 7D DE A3 EE 5D 22 13 7A 13 A3 B8 08 6E 13 86 B3 26 3E 69 E9 57 0D C2 BD 00 B1 1F 66 EE 76 4A D5 05 02 51 20 E9 81 C9 9F C6 DA 86 BC 99 1D 2F 7C 14 A9 1C 30 EB 89 45 5D C2 62 75 43 E3 42 3C DA 36 63 2F 4B 88 EB FF E8 D6 28 0D F4共132字节密文。
问题1:此时MTK没有响应卡证发过来的这包数据,通过验证发现这132个字节已经放到了串口缓冲里,但串口没有发出消息MSG_ID_UART_READY_TO_READ_IND通知MTK去缓冲里取数据。
测试过程2:
1、 MTK重新发送指令0x05 0x00 0x00 0x00给卡证,卡证回复0xcc;
2、 MTK从串口缓冲中取出了133个字节,包括之前卡证回复的132字节+0xCC。
问题2:MTK 的uart在第二次交互过程中收数据后为什么没有发送消息MSG_ID_UART_READY_TO_READ_IND呢?
测试过程3、用电脑串口模拟以上数据交互过程,所用的数据均为与卡证回复的数据相同,结果显示MTK与电脑串口通信时并没有类似或相同的问题,能够正常通行。
问题3:卡证模块的串口与电脑usb转串口引出来的串口有什么区别吗?
测试过程4、
1、 将测试过程1中第二次交互时,卡证收到MTK发送的02 00 10 00 + 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11共132个字节后恢复的密文数据减半为66字节时,发现这种情况,串口发出了消息MSG_ID_UART_READY_TO_READ_IND,使程序能响应该包数据并正确处理。
2、 接下来将卡证回复的数据字节数据改为98字节和148字节均和测试过程1相同。
问题4:到底是什么造成卡证的串口发出来的数据不同于电脑串口发出来的数据呢?
问题解决:
以上的问题是由于MTK在uart1配置时没有加上校验位。
解决:卡证模块串口通信采用了奇校验,与电脑通信时,pc上的调试助手可以不设校验,但与MTK通信时如果MTK上不设奇校验就会出现上述错误。
二、程序源码:
#include "TicketAppProt.h"
#include "uart_sw.h"
#include "uart_hw.h"
#include "MMI_features.h"
#include "PixtelDataTypes.h"
#include "gdi_include.h"
#include "wgui.h"
#include "gui.h"
#include "Globaldefs.h"
#include "CustDataRes.h"
#include "gui_themes.h"
#include "wgui_categories.h"
#include "wgui_categories_util.h"
#include "wgui_softkeys.h"
#include "HistoryGprot.h"
#include "OrganizerDef.h"
#include "TicketAppDefs.h"
#include "..\plutommi\mmi\TicketApp\TicketAppInc\TicketAppResDef.h"
#include "..\plutommi\mmi\TicketApp\TicketAppInc\TicketAppProt.h"
#include "MainMenudef.h"
#include "Unicodexdcl.h"
#include "Gui.h"
#include "Conversions.h"
#include "Wgui_categories_list.h"
U8 gDAbuffer[COS_DA_MAX_LEN];
U16 gDAbuflen;
static kal_uint8 ghSleepMode;// 睡眠模式句柄
// 我们要用到的串口之前的占用者
static module_type gnOrigUartOwner;
static kal_bool gbUartInitialized = KAL_FALSE;
void CosUartHandler(void *msg);
void delay(U32 Ms)//单位ms
{
U64 n, i;
n = Ms * 2500;
while(n)
{
;
n--;
}
}
UARTDCBStruct UART_DefaultConfig =
{
UART_BAUD_9600,//UART_BAUD_115200, /* baud; */
len_8, /* dataBits; */
sb_1, /*stopBits; */
pa_odd, /* parity; */
fc_none, /*no flow control*/
0x11, /* xonChar; */ //zzw
0x13, /* xoffChar; */
KAL_FALSE
};
UARTDCBStruct *DCBdefault;
void CosUartInit(void)
{
if(gbUartInitialized)
{
return;
}
// 禁止休眠,休眠后串口收发会有问题
ghSleepMode = L1SM_GetHandle();
L1SM_SleepDisable(ghSleepMode);
/* UART init */
gnOrigUartOwner = UART_GetOwnerID(COS_UART);// 记录我们要用的串口的当前占有者
UART_SetOwner(COS_UART, MOD_COS);//申明要占用这个串口
DCBdefault = (UARTDCBStruct *)&UART_DefaultConfig;
UART_SetDCBConfig(COS_UART, DCBdefault,MOD_COS);//配置串口
UART_ClrTxBuffer(COS_UART, MOD_COS);//清空发送缓冲区
UART_ClrRxBuffer(COS_UART, MOD_COS);//清空接收缓冲区
//注册一个事件钩子函数,当串口(任何)有数据到达时,我们的钩子函数将被调用
SetProtocolEventHandler(CosUartHandler, MSG_ID_UART_READY_TO_READ_IND);
gbUartInitialized = KAL_TRUE;
}
void exit_uart(void)
{
if(gbUartInitialized)
{
// 恢复成原有的端口占用者
UART_SetOwner(COS_UART, (kal_uint8)gnOrigUartOwner);
// 允许休眠
L1SM_SleepEnable(ghSleepMode);
gbUartInitialized = KAL_FALSE;
}
}
U8 CosWrite(U8 *buf, U16 buflen, UART_PORT port, module_type ownerid)
{
U8 ret = FALSE;
U16 sent;
module_type UART_Owner = 0;
sent = 0;
// 发送前清FIFO和Buffer,注意:这一步必须做,否则收发会有问题
UART_Purge(port, RX_BUF, ownerid);
UART_Purge(port, TX_BUF, ownerid);
UART_ClrTxBuffer(port, ownerid);
UART_ClrRxBuffer(port, ownerid);
sent = UART_PutBytes(port, (kal_uint8 *)buf, (kal_uint16)buflen, ownerid);
if (sent == buflen)
ret = TRUE;
return ret;
}
U16 CosRead(U8 *buf, U16 maxlen, UART_PORT port, module_type ownerid)
{
U16 readlen;
U16 avail;
U16 retlen = 0;
U8 status = 0;
// 收取数据,超出最大包长的数据将简单丢弃,这一层需要具体的应用协议做相应处理
while ((avail = UART_GetBytesAvail(port) && retlen < maxlen)>0)
{
if (avail + retlen > maxlen)
avail = maxlen - retlen;
readlen = UART_GetBytes(port, (kal_uint8 *)(buf+retlen),(kal_uint16)avail, &status, ownerid);
retlen += readlen;
}
//retlen=UART_GetBytes(port,(kal_uint8 * )buf, (kal_uint16)maxlen, &status, ownerid);
// 读完之后,清除接收Buffer
UART_ClrRxBuffer(port, ownerid);
return retlen;
}
U32 CosRecv(kal_uint8 *recv_buf, kal_uint32 recv_len)
{
kal_uint8 status = 0;
kal_uint16 readlen,totallen;
readlen=UART_GetBytes(COS_UART, recv_buf, recv_len, &status, MOD_COS);
UART_Purge(COS_UART, RX_BUF, MOD_COS);
UART_ClrRxBuffer(COS_UART, MOD_COS);
return readlen;
}
kal_uint8 jiami[132] ={0x02, 0x00, 0x10, 0x00,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 };
kal_uint8 jiami1[66] ={0x02, 0x00, 0x10, 0x00,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11};
void CosUartHandler(void *msg)
{
U8 mydatabuf[1024], i;
uart_ready_to_read_ind_struct *tmp = (uart_ready_to_read_ind_struct *)msg;
if (UART_GetOwnerID(tmp->port) != MOD_COS)
return ;
if (tmp->port != COS_UART)
return ;
gDAbuflen = CosRead(gDAbuffer, sizeof(gDAbuffer), COS_UART, MOD_COS);
//gDAbuflen = CosRecv(gDAbuffer, sizeof(gDAbuffer));
if(gDAbuffer[0]==0xCC)
{
show_chinese((kal_uint8 *)"收到CC", 14, 25, 75, UI_COLOR_DARK_GREY);
delay(1000);
CosWrite(jiami, sizeof(jiami), COS_UART, MOD_COS);
show_chinese((kal_uint8 *)"发送明文128字节", 32, 25, 100, UI_COLOR_DARK_GREY);
memset(gDAbuffer, 0, sizeof(gDAbuffer));
gui_BLT_double_buffer(0, 0, UI_device_width - 1, UI_device_height - 1);
//clear_screen();
return;
}
if((gDAbuffer[0]==0x02) && (gDAbuffer[1]==0x00) && (gDAbuffer[2]==0x11) && (gDAbuffer[3]==0x00))
{
show_chinese((kal_uint8 *)"收到密文128字节", 32, 25, 125, UI_COLOR_DARK_GREY);
gDAbuffer[2] = 0x20;
delay(1000);
CosWrite(gDAbuffer, 132, COS_UART, MOD_COS);
show_chinese((kal_uint8 *)"发送密文128字节", 32, 25, 150, UI_COLOR_DARK_GREY);
gui_BLT_double_buffer(0, 0, UI_device_width - 1, UI_device_height - 1);
memset(gDAbuffer, 0, sizeof(gDAbuffer));
return;
}
if((gDAbuffer[0]==0x02) && (gDAbuffer[1]==0x00) && (gDAbuffer[2]==0x22) && (gDAbuffer[3]==0x00))
{
show_chinese((kal_uint8 *)"收到解密后的明文", 34, 25, 175, UI_COLOR_DARK_GREY);
show_chinese((kal_uint8 *)"加解密OK", 18, 25, 200, UI_COLOR_DARK_GREY);
gui_BLT_double_buffer(0, 0, UI_device_width - 1, UI_device_height - 1);
memset(gDAbuffer, 0, sizeof(gDAbuffer));
return;
}
else
{
show_chinese((kal_uint8 *)"失败", 6, 25, 225, UI_COLOR_DARK_GREY);
CosWrite(gDAbuffer, gDAbuflen, COS_UART, MOD_COS);
gui_BLT_double_buffer(0, 0, UI_device_width - 1, UI_device_height - 1);
return;
}
}