Cómo utilizar el puerto serie CC2530 en Zstack
, el principio de funcionamiento de las interrupciones y luego analizar el procesamiento de la entrada. y buffers de salida, etc., y aprende El lector siguió la pila de protocolos
La capa inferior del puerto serie subió completamente, dio la vuelta, dio la vuelta nuevamente y se confundió.
De hecho, desde el punto de vista de la aplicación, no necesitamos profundizar en el mecanismo de funcionamiento del puerto serie Zstack.
No es necesario pensar en cómo DMA y. interrumpe el trabajo. Para lograr esto, solo necesitamos llamar a algunas funciones simples para lograr un uso regular del puerto serie.
De hecho, la pila ya está lista para usar el puerto serie, entonces ¿por qué deberíamos preocuparnos por la implementación del hardware subyacente
? Los adoptantes deben pensar en la pila como una plataforma, y las aplicaciones encima de la plataforma son nuestros objetivos. A continuación hablaré sobre
cómo aprovechar la plataforma existente de la pila para implementar su propia aplicación de puerto serie. La plataforma existente que mencioné aquí es el paquete MT que viene con Zstack.
De hecho, el paquete MT en Zstack es bastante poderoso. A través de la herramienta ZTOOL proporcionada por TI, puede usar serial
<. p> p>¡Puertos para interactuar con toda la pila! No diré mucho sobre esto. Los estudiantes interesados pueden estudiar el paquete de software MT
específicamente.
En segundo lugar, utilizando
En el paquete de software MT, siempre hay una inicialización del puerto serie, es decir, la función de procesamiento de datos del puerto serie disponible, y varias funciones clave aparecen en p>
En el archivo MT_Uart.c.
Extraigamos algunas funciones clave para explicar (extraeré y comentaré las oraciones importantes):
La primera función
void MT_UartInit ()
{ / / Esta es la función de inicialización del puerto serie en MT. Su función principal es inicializar algunas reglas de funcionamiento del puerto serie
halUARTCfg_t uartConfig;
App_TaskID = 0; se utiliza para procesar datos en serie Ignorar primero
uartConfig.configured = TRUE;
uartConfig.baudRate = MT_UART_DEFAULT_ BAUDRATE;
//La velocidad en baudios predeterminada es. 38400; se puede cambiar, pero es posible. Surgirán nuevas preguntas y habrá explicaciones más específicas, por lo que no entraré en detalles;
uartConfig.flowControl = FALSE;
uartConfig.maxBufSize = MT_UART_DEFAULT_MAX_RX_BUFF;
uartConfig.tx.maxBufSize = MT_UART_DEFAULT_MAX_TX_BUFF;
uartConfig.idleTimeout = MT_UART_DEFAULT_IDLE_TIMEOUT;
uartConfig.intEnable = TRUE;
#if definido (ZTOOL_P1) |definido (ZTOOL_P2)
uartConfig.callBackFunc = MT_UartProcessZToolData;
// Si elige utilizar ZTOOL en tiempo de compilación, MT_UartProcessZtoolData manejará los datos recibidos desde el puerto serie
// Cadena de datos
#elif definido (UartProcessZAppData
// Función para procesar la cadena de datos del puerto serie
(*Si usa los dos pines serie del puerto CC2530 P0. Si usa los dos pines serie del puerto P1, debe definir ZTOOL_P2 para ZAPP_P1, que también es el caso para ZAPP_P2*)
#else
uartConfig.callBackFunc = NULL;
// Si está interesado en escribir su propio controlador de puerto serie, puede implementar My_UartProcessData
// función aquí y complete y reemplace NULL aquí.
#endif
#if definido (MT_UART_DEFAULT_PORT)
HalUARTOpen (MT_UART_DEFAULT_PORT, amp. uartConfig);
// Si está definido El puerto serie predeterminado (0 o 1) y el puerto serie está abierto, entonces esta función HalUartOpen realizará mucho trabajo, especialmente
//Esencialmente, es solo la inicialización. No necesito dar más detalles sobre este punto.
Cabe señalar que esta función pasa como parámetro el uartConfig previamente inicializado
//!
#else
(void)uartConfig;
#endif
#if definido (ZAPP_P1) ||definido (ZAPP_P2)
MT_UartMaxZAppBufLen = 1;
MT_UartZAppRxStatus = MT_UART_ZAPP_RX_READY;
Con estas dos oraciones, si no desea utilizar MT_UartProcessZToolData para procesar datos del puerto serie, simplemente hágalo él. . . .
// Luego tenemos que estudiar en profundidad el mecanismo del puerto serie. Hay demasiados artículos en Internet para explicarlo. Léelo tú mismo más adelante.
/. //MT_UartProcessZToolData.
#endif
}
Segunda función
void MT_ UartRegisterTaskID( byte taskID )
{ p>
App_TaskID = taskID;
}
La tercera función
void MT_UartProcessZToolData (puerto uint8, evento uint8)
osal_msg_deallocate ( (uint8 *)pMsg );
}
Avancemos y veamos cuál es este mensaje. No muy lejos del comienzo de la función MT_UartProcessZToolData se encuentra el siguiente segmento de secuencia del programa
:
if (pMsg)
{
pMsg-gt; hdr.event = CMD_SERIAL_MSG;
pMsg-gt; mensaje = (uint8*)(pMsg 1);
pMsg-gt;
p>state=CMD_STATE1;
}
Como se puede ver desde aquí, esta función crea un encabezado de mensaje con CMD_SERIAL_MSG como mensaje, luego
osal_msg_send El mensaje enviado a la tarea se mostrará como CMD_SERIAL_MSG. . . . . . .
Ok, después de leer las tres funciones anteriores, intentemos usarlas:
Tome el ejemplo de GenericApp como ejemplo:
void GenericApp_Init( byte task_id )
| agregado por kennan
MT_UartRegisterTaskID(GenericApp_TaskID);
}
Echa otro vistazo a MT_UartRegisterTaskID(GenericApp_TaskID): p>
void MT_UartRegisterTaskID( byte taskID )
{
App_TaskID = taskID;
}
Bueno, de esta manera , utilizamos con éxito MT_UartProcessZToolData para procesar datos desde el puerto serie, y los
datos procesados se empaquetan y envían a la tarea GenericApp_TaskID
A continuación, veamos cómo están los datos en GenericApp_TaskID. procesado /p>
En la función de procesamiento principal de GenericApp:
UINT16 GenericApp_ProcessEvent( byte task_id, eventos UINT16)
{
if (eventos). amp; SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t*)osal_msg_receive( GenericApp_TaskID );
mientras ( MSGpkt )
{
cambiar ( MSGpkt-gt; hdr.
{
caso ZDO_CB_MSG:
GenericApp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt ); p>
romper;
caso KEY_CHANGE:
GenericApp_HandleKeys( ((keyChange_t *)MSGpkt)-gt; estado, ((keyChange_t
*) MSGpkt) -gt; claves );
romper
/Aumentar
Caso CMD_SERIAL_MSG:
ProcessUartData((mtOSALSerialData_t *)MSGpkt );
/// Esta es su propia implementación de función. ... haz lo que quieras. Haz lo que quieras. Si desea enviar los
//datos recibidos de vuelta al puerto serie, simplemente llame a HalUARTWrite.
}
Si no sabes cómo extraer la información serial y procesarla, tendré la amabilidad de implementar una función ProcessUartData() para ti
.
La función de esta función es enviar los datos recibidos desde CM0 al puerto serie hasta el último byte de la carga útil
, excluyendo el byte de verificación.
ProcessUartCommand((mtOSALSerialData_t *)MSGpkt)
{ // Para realizar el siguiente trabajo correctamente, utilice el tipo mtOSALSerialData_t para apuntar al paquete zigbee completo (en lugar del paquete serial
/paquete de puerto).
uint8 *pMsg;
pMsg = MSGpkt-gt;
//Define un puntero a donde se almacenan los datos recibidos en serie reales. algunos otros encabezados dentro de MSGptk oh.
switch (MSGpkt-gt;hdr.event)
{
case CMD_SERIAL_MSG: //Si es un serial mensaje. . . .
HalLedSet(HAL_LED_RED, HAL_LED_MODE_FLASH);
/Usa los LED para indicar que se han recibido los datos
uint8 *pBuffer;
uint8 datalength;
uint8 i.
// Defina algunas variables para prepararse para extraer los datos del paquete recibido y escribirlos nuevamente en el puerto serie
datalength = *pMsg;
// El primer byte del paquete de datos en serie es la longitud de los datos
pBuffer = osal_mem_alloc(datalength);
// Asigne un bloque de memoria y prepárese para extraer los datos del mensaje en serie
if(pBuffer != NULL)
{
for (i = 0 ; i lt; datalength; i )
*pBuffer = *pMsg;
// Busque y extraiga los datos seriales en el mensaje uno por uno según el número de longitudes de datos. (¿desangrar el charco de qué?). Pool
//Lo que hay dentro que necesita ser sangrado, ¿entiendes?
HalUARTWrite(0, pBuffer, datalength);
// Extraiga la sangre de los datos del puerto serie y escríbala nuevamente en el puerto serie, es decir, envíela al asistente de puerto serie para visualización
Osal_memfree(pBuffer);
//Recuerda usar la memoria para aplicaciones dinámicas y luego liberarla
} p>
romper;
predeterminado:
romper
}
}
Nota: Dado que ZTOOL envía datos en un formato determinado, si utiliza el asistente del puerto serie para realizar pruebas, los datos deben enviarse en un formato determinado.
Si no desea seguir este formato, puede modificar los procedimientos relacionados en MT_UartProcessZToolData
. Este método es muy práctico para aplicaciones que quieren controlar zigbee a través de una PC, porque los comandos y datos que envía tu PC generalmente los tienen. Si no usas el formato MT, necesitas estandarizar un formato. >
existe, simplemente lo tomamos prestado.
Para MT_UartProcessZAppData, el método de procesamiento es ZAPP_P1 o ZAPP_P2 definido por usted
El mecanismo es similar, excepto que el formato no está especificado, por lo que puede procesarlo más libremente. No digo más aquí.
Además, si realmente no sabes cuál es el resultado xor de esa larga cadena de datos al realizar la prueba, también puedes ir a la
función MT_UartProcessZToolData y buscar: p>
//if ((MT_UartCalcFCS ((uint8*)amp; pMsg- gt; msg[0], MT_RPC_FRAME_HDR_SZ
LEN_Token) == FSC_Token))
{
osal_msg_send(App_TaskID, (byte *)pMsg);
}
else
//{
// osal_msg_deallocate ( (uint8 *)pMsg );
//}
Comente las ubicaciones que marqué en rojo para que no marque y no tenga para calcular el resultado xor, pero cuando envía datos,
esta ubicación sigue siendo necesaria. Simplemente complete los 0 que desee.