______________________________________________________________________ > < > RS232 driver v1.07 < > for < > PICos18 release 2.03 < > < > PICos18 - Real-time kernel for PIC18 family < > < > < > www.picos18.com www.pragmatec.net < >______________________________________________________________________< This file contains all necessary informations to use properly the PIC18 RS232 driver for PICos18 v2.03. This driver lets you design a multi-task application using the same USART without being concerned by the USART shared access. Then every task of your application can print message without being necessarily synchronised to the others. ______________________________________________________________________ > < > I - Zip file content < >______________________________________________________________________< The drv_rs zip file contains : - drv_rs.c - drv_rs.h : header file - drv_rs.txt : this file To use the PICos18 RS232 driver, first unzip the file. Place the C and H file in your project directory. This driver is supposed to be use with PICos18 and has been tested with MPLAB 7.10 and C18 v2.42. Do not use this driver at a frequency lower than 8 Mhz (use the PIC18 PLL to increase the internal frequency). ______________________________________________________________________ > < > II - Hardware settings < >______________________________________________________________________< Adapt the SPBRG register according to the oscillator frequency to set the correct baud rate generator (file drv_rs.c). /* Change baud rate here [cf datasheet]*/ /* SPBRG = 255; for 9600 [40MHZ only]*/ /* SPBRG = 21; for 115200 [40MHZ only]*/ SPBRG = 21; Look up the PIC18 datasheet for different settings. ______________________________________________________________________ > < > III - TASCDESC settings (1) < >______________________________________________________________________< Update also the tascdesc.c file to take into account the new RS driver in your application : /********************************************************************** * ----------------------- TASK & STACK DEFINITION -------------------- **********************************************************************/ DeclareTask(Example); DeclareTask(RS_Drv); ... volatile unsigned char stack0[DEFAULT_STACK_SIZE]; volatile unsigned char stack_rs[DEFAULT_STACK_SIZE]; ... ______________________________________________________________________ > < > IV - TASCDESC settings (2) < >______________________________________________________________________< Finally add the task and alarm descriptor to the tascdesc.c file : ... /********************************************************************** * ------------------------------ RS task ----------------------------- **********************************************************************/ rom_desc_tsk rom_desc_RS_DRV = { RDV_RS_PRIO, /* prioinit from 0 to 15 */ stack_rs, /* stack address (16 bits) */ RS_Drv, /* start address (16 bits) */ READY, /* state at init phase */ RS_DRV_ID, /* id_tsk from 0 to 15 */ sizeof(stack_rs) /* ctx address (16 bits) */ }; ... To use the RS232 we propose a EXAMPLE task wich prints some string of data. Because the task is a periodic one, we create an alarm : AlarmObject Alarm_list[] = { /******************************************************************* * ----------------------- Example task ---------------------------- *******************************************************************/ { OFF, /* State */ 0, /* AlarmValue */ 0, /* Cycle */ &Counter_kernel, /* ptrCounter */ Example, /* TaskID2Activate */ ALARM_EVENT, /* EventToPost */ 0 /* CallBack */ } }; ______________________________________________________________________ > < > V - TASK Settings < >______________________________________________________________________< Open define.h and add this 3 definitions with correct value : #define RS_NEW_MSG 0x10 #define RS_RCV_MSG 0x20 #define RS_QUEUE_EMPTY 0x10 #define RS_QUEUE_FULL 0x20 #define RS_DRV_ID 6 #define RDV_RS_PRIO 8 #define EXAMPLE_ID 4 #define EXAMPLE_PRIO 5 The RS232 task is considered to be a driver, that means you have to give one of the highest priority to the RS232 driver to let it run each time the RS buffer is updated. Adapt the values to your application is necessary (event values...). ______________________________________________________________________ > < > VI - ISR connection < >______________________________________________________________________< Open the file int.c and declare the external RS232 ISR function : extern void AddOneTick(void); extern void RS_RX_INT(void); // <= here extern void RS_TX_INT(void); // <= here void InterruptVectorL(void); void InterruptVectorH(void); And complete the InterruptVector function : void InterruptVectorL(void) { EnterISR(); if (INTCONbits.TMR0IF == 1) AddOneTick(); if ((PIR1bits.RCIF)&(PIE1bits.RCIE)) RS_RX_INT(); if ((PIR1bits.TXIF)&(PIE1bits.TXIE)) RS_TX_INT(); LeaveISR(); } ______________________________________________________________________ > < > VII - RS driver usage < >______________________________________________________________________< In the Example task, include the driver header: #include "drv_rs.h" #include #include And declare a RS message (type RS_message_t): RS_ message_t RS_msg; In the task, a Printf function has been added to automaticaly prepare the RS_message_t buffer with any kind of data. See hereafter a basic example to print à "hello !" sentence with a counter value to HyperTerminal under Microsoft Windows(TM): #include "define.h" #include "drv_rs.h" #include #include /********************************************************************** * Definition dedicated to the local functions. **********************************************************************/ int Printf (const rom char *fmt, ...); /********************************************************************** * Variables shared with the rest of application. **********************************************************************/ RS_message_t RS_msg; unsigned char buffer[50]; /* This is just an exemple to show how to declare a const string in rom */ far rom char *example = "Oops !"; /********************************************************************** * ------------------------- Example TASK ---------------------------- * * **********************************************************************/ TASK(Example) { SetRelAlarm(0, 1000, 1000); while(1) { WaitEvent(ALARM_EVENT); ClearEvent(ALARM_EVENT); Printf("hello !\r\n"); } } /********************************************************************** * Function in charge of structure registration and buffer transmission. * * @param string IN const string send to the USART port * @return void **********************************************************************/ int Printf (const rom char *fmt, ...) { va_list ap; int n; RS_enqMsg(&RS_msg, buffer, 0); va_start (ap, fmt); n = vfprintf (_H_USER, fmt, ap); va_end (ap); SetEvent(RS_DRV_ID, RS_NEW_MSG); WaitEvent(RS_QUEUE_EMPTY);ClearEvent(RS_QUEUE_EMPTY); return n; } With such an example you should see under HyperTerminal : hello ! hello ! hello ! ______________________________________________________________________ > < > VIII - Reception < > Fixed length buffer < >______________________________________________________________________< All the data recieved from the RS232 are store in only one reception buffer. In order to capture the content of the reception buffer, you have to create a new task waiting for an event corresponding to the fact the reception buffer is full. This let you design a protocol layer, for instance a PROFIBUS driver that catches the reception buffer then analyze the content and dispatch the content function to the sub-address included. In the waiting task don't forget to include the appropriate header files: #include "drv_rs.h" #include #include And declare a RS message for reception only (type RS_message_t): RS_message_t RS_rcv_msg; Create a buffer to recieve the content of the reception buffer when it is full : unsigned char block[64]; Register the waiting task so that the RS232 driver will wake it up when the reception buffer is full : TASK(Protocol) { RS_RCV_Register(&RS_rcv_msg, (unsigned char*)(block), sizeof(block), 0); while (1) { WaitEvent(RS_QUEUE_FULL); ClearEvent(RS_QUEUE_FULL); switch(block[0]) // the command field for instance { case ACTION_INIT : InitHardware(); break; case ... } } } ______________________________________________________________________ > < > IX - Reception < > Special character expected < >______________________________________________________________________< Insteed of managing a fixed length buffer, you can wait for a specific character like a carriage return of a 0x17 to specify the end of transmission. In the waiting task don't forget to include the appropriate header files: #include "drv_rs.h" #include #include And declare a RS message for reception only (type RS_message_t): RS_message_t RS_rcv_msg; Create a buffer to recieve the content of the reception buffer when it is full : unsigned char block[64]; Register the waiting task so that the RS232 driver will wake it up when the expected character is detected : TASK(Protocol) { unsigned char i; RS_RCV_Register(&RS_rcv_msg, (unsigned char*)(block), 0, '\r'); while (1) { WaitEvent(RS_QUEUE_FULL); ClearEvent(RS_QUEUE_FULL); i = 0; while (block[i] != '\r') i++; block[i+1] = 0; Printf("%s\r\n", block); } } The example above prints at screen each sentence that has been sent from HyperTerminal. ______________________________________________________________________ > < > X - Conclusion < >______________________________________________________________________< Be carrefull when compiling : some warning can appear that have not been resolved, they is no trouble related to. In this example you can see only one task using the PIC18 USART. In fact you can add many other tasks sharing this USART without being concerned by the shared access of the USART. This lets you debug easily your tasks with some printf functions... This RS232 driver is provided from the PICos18 web site with other drivers dedicated to oher peripherals. Some zip files are also provided to be used with a driver. For instance a "Profibus protocol" file should be delivered to manage a Profibus based on this RS232 driver. Do not hesitate to check periodicaly the www.picos18.com web site in order to download the last versions of PIC18 drivers for PICos18. /* End of File : drv_rs.txt */