CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

trouble getting 16 bits from timer0 and timer1

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
tatokash



Joined: 08 Aug 2007
Posts: 6

View user's profile Send private message

trouble getting 16 bits from timer0 and timer1
PostPosted: Thu Sep 06, 2007 1:36 pm     Reply with quote

With PCWH v. 4.04, I'm having trouble putting the full 16 bits from Timer 1 into a string using sprintf. Processor is a PIC18F2550. I'm trying to pass the string via USB packet to a PC.


Code:

int16 UpCount;
...
setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);
...
UpCount = get_timer1();
...
sprintf(ReturnMessage,"T0=%Lx\n\r",UpCount);



I never get a value greater than FF.

'T0=000000FF' is the string returned.


I tried
Code:
unsigned int16 TMR1;
#locate TMR1=0x0FCE

and
Code:
#byte TMR1H = 0xfcf
#byte TMR1L = 0xfce

but both give me the same results.

What am I doing wrong? How do I get the high byte of timer1?
_________________
Don't ever stop learning...
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Sep 07, 2007 1:38 am     Reply with quote

1. Post a complete (but short) test program where you show all
variable declarations, #fuses statement, etc. It should be compilable.

2. Post the full compiler version. It's a 4-digit number in x.xxx format.
tatokash



Joined: 08 Aug 2007
Posts: 6

View user's profile Send private message

PostPosted: Fri Sep 07, 2007 12:24 pm     Reply with quote

Compiler version is 4.040.

I have managed to get timer 0 to work. Still not sure why timer 1 doesn't work.

The end result will eventually be a DC servo controller. Timers 0 and 1 are the encoder inputs and timer 2 is used for the CCP PWM. I've pared down the code to reduce confusion and illustrate only the timers. The bulk of the includes is taken from the example code. My code is added at the end.

Uncomment the #define for TEST0, TEST1, or TEST2 to test each one.

My program:
Code:
#include <18F2550.h>

#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOBROWNOUT,MCLR
#use delay(clock=48000000)
#use FAST_IO

#DEFINE USB_HID_DEVICE     FALSE

#define USB_EP1_TX_ENABLE  USB_ENABLE_BULK  //turn on EP1 for IN bulk/interrupt transfers
#define USB_EP1_RX_ENABLE  USB_ENABLE_BULK  //turn on EP1 for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE    64  //size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE    64   //size to allocate for the rx endpoint 1 buffer

#include <pic18_usb.h>
#include "test.h"
#include <usb.c>
#include <string.h>

#byte T0CON = 0xfd5
#byte T1CON = 0xfcd

//Pick your method of reading timer value
//#define TEST0
//#define TEST1
#define TEST2

#ifdef TEST1
   #byte TMR1H = 0xfcf
   #byte TMR1L = 0xfce
   
   #byte TMR0H = 0xfd7
   #byte TMR0L = 0xfd6
#endif

#ifdef TEST2
   unsigned int16 TMR0;
   #locate TMR0=0x0fd6
   
   unsigned int16 TMR1;
   #locate TMR1=0x0fce
#endif

void usb_data_task(void)
{
   int8 ret_count;
   usb_gets(1,16,ret_count,500);
}

void setup()
{
   //Setup Timers
   setup_timer_0(RTCC_EXT_L_TO_H | RTCC_DIV_1);
   setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);
   setup_timer_2(T2_DIV_BY_4, TIMER_2_PERIOD, 1);
   
   output_low(M2_ENAB);

   setup_ccp1(CCP_PWM);
   set_pwm1_duty(PWM_STOPPED);
   
   set_timer0(0);
   T0HiWord = 0;
   set_timer1(0);
   T1HiWord = 0;
   DnCount = 0;
   UpCount = 0;
   
   //Setup and initialize I/O
   SET_TRIS_A(TRIS_WORD_A);
   SET_TRIS_B(TRIS_WORD_B);
   SET_TRIS_C(TRIS_WORD_C);

   PWMDutyCyc = PWM_STOPPED;

   //Set up Interrupts
      enable_interrupts(GLOBAL);

}

void main(void)
{

   setup();
   usb_init_cs();

   for(i=0;i<RETURN_MESSAGE_STRING_LENGTH;i++)
   {
      ReturnMessage[i]=0;
   }
   while (TRUE)
   {
      usb_task();
      if(usb_enumerated())
      {
         if (usb_kbhit(1))
         {
            /* Eventually commands will be received and interpretted. 
               For now, if I receive anything from the host I turn my motor
               on or off.*/
            usb_get_packet(1,CommandString,MAX_COMMAND_STRING_LENGTH); 
            set_pwm1_duty(PWM_STOPPED+10);
            output_toggle(M2_ENAB);
         }
         
#ifdef   TEST0
         timer0_read = get_timer0();
         timer1_read = get_timer1();
#endif
   
#ifdef   TEST1
         timer0_read = 0;
         timer0_read = TMR0H;
         timer0_read = (timer0_read * 256) + TMR0L;
         
         timer1_read = 0;
         timer1_read = TMR1H;
         timer1_read = (timer1_read * 256) + TMR1L;
#endif
   
#ifdef   TEST2
         timer0_read = TMR0;
         timer1_read = TMR1;
#endif
   
         t0con_reg = T0CON;
         t1con_reg = T1CON;
         
         sprintf(ReturnMessage,"T0=%Lx\n\rT1=%Lx\n\rT0CON=%x, T1CON=%x\n\r",timer0_read,timer1_read,t0con_reg,t1con_reg);
         res=usb_put_packet(1,ReturnMessage,RETURN_MESSAGE_STRING_LENGTH,USB_DTS_TOGGLE);
      }
   }
}

My includes:
Code:
#IFNDEF __USB_DESCRIPTORS__
#DEFINE __USB_DESCRIPTORS__

#include <usb.h>

//////////////////////////////////////////////////////////////////
///
///   start config descriptor
///   right now we only support one configuration descriptor.
///   the config, interface, class, and endpoint goes into this array.
///
//////////////////////////////////////////////////////////////////

   #DEFINE USB_TOTAL_CONFIG_LEN      32 //config+interface+class+endpoint

   //configuration descriptor
   char const USB_CONFIG_DESC[] = {
   //config_descriptor for config index 1
         USB_DESC_CONFIG_LEN,     //length of descriptor size
         USB_DESC_CONFIG_TYPE,         //constant CONFIGURATION (0x02)
         USB_TOTAL_CONFIG_LEN,0,  //size of all data returned for this config
         1,      //number of interfaces this device supports
         0x01,                //identifier for this configuration.  (IF we had more than one configurations)
         0x00,                //index of string descriptor for this configuration
         0xC0,                //bit 6=1 if self powered, bit 5=1 if supports remote wakeup (we don't), bits 0-4 reserved and bit7=1
         250,                //maximum bus power required (maximum milliamperes/2)  (0x32 = 100mA)
//       0x32,                //maximum bus power required (maximum milliamperes/2)  (0x32 = 100mA)

   //interface descriptor 0 alt 0
         USB_DESC_INTERFACE_LEN,  //length of descriptor
         USB_DESC_INTERFACE_TYPE,      //constant INTERFACE (0x04)
         0x00,                //number defining this interface (IF we had more than one interface)
         0x00,                //alternate setting
         2,       //number of endpoints, not counting endpoint 0.
         0xFF,                //class code, FF = vendor defined
         0xFF,                //subclass code, FF = vendor
         0xFF,                //protocol code, FF = vendor
         0x00,                //index of string descriptor for interface

   //endpoint descriptor
         USB_DESC_ENDPOINT_LEN, //length of descriptor
         USB_DESC_ENDPOINT_TYPE,     //constant ENDPOINT (0x05)
         0x81,              //endpoint number and direction (0x81 = EP1 IN)
         0x02,              //transfer type supported (0 is control, 1 is iso, 2 is bulk, 3 is interrupt)
         USB_EP1_TX_SIZE & 0xFF,USB_EP1_TX_SIZE >> 8,         //maximum packet size supported
         0x01,              //polling interval in ms. (for interrupt transfers ONLY)

   //endpoint descriptor
         USB_DESC_ENDPOINT_LEN, //length of descriptor
         USB_DESC_ENDPOINT_TYPE,     //constant ENDPOINT (0x05)
         0x01,              //endpoint number and direction (0x01 = EP1 OUT)
         0x02,              //transfer type supported (0 is control, 1 is iso, 2 is bulk, 3 is interrupt)
         USB_EP1_RX_SIZE & 0xFF,USB_EP1_RX_SIZE >> 8,         //maximum packet size supported
         0x01,              //polling interval in ms. (for interrupt transfers ONLY)

  };

   //****** BEGIN CONFIG DESCRIPTOR LOOKUP TABLES ********
   //since we can't make pointers to constants in certain pic16s, this is an offset table to find
   //  a specific descriptor in the above table.

   //NOTE: DO TO A LIMITATION OF THE CCS CODE, ALL HID INTERFACES MUST START AT 0 AND BE SEQUENTIAL
   //      FOR EXAMPLE, IF YOU HAVE 2 HID INTERFACES THEY MUST BE INTERFACE 0 AND INTERFACE 1
   #define USB_NUM_HID_INTERFACES   0

   //the maximum number of interfaces seen on any config
   //for example, if config 1 has 1 interface and config 2 has 2 interfaces you must define this as 2
   #define USB_MAX_NUM_INTERFACES   1

   //define how many interfaces there are per config.  [0] is the first config, etc.
   const char USB_NUM_INTERFACES[USB_NUM_CONFIGURATIONS]={1};

   #if (sizeof(USB_CONFIG_DESC) != USB_TOTAL_CONFIG_LEN)
      #error USB_TOTAL_CONFIG_LEN not defined correctly
   #endif


//////////////////////////////////////////////////////////////////
///
///   start device descriptors
///
//////////////////////////////////////////////////////////////////

   //device descriptor
   char const USB_DEVICE_DESC[] ={
         USB_DESC_DEVICE_LEN,          //the length of this report
         0x01,                //constant DEVICE (0x01)
         0x10,0x01,           //usb version in bcd
         0x00,                //class code (if 0, interface defines class.  FF is vendor defined)
         0x00,                //subclass code
         0x00,                //protocol code
         USB_MAX_EP0_PACKET_LENGTH,   //max packet size for endpoint 0. (SLOW SPEED SPECIFIES 8)
         0x60,0x1b,           //vendor id 0x1B60
         0x05,0xff,           //product id 0xff05
         0x00,0x01,           //device release number
         0x01,                //index of string description of manufacturer. therefore we point to string_1 array (see below)
         0x02,                //index of string descriptor of the product
         0x00,                //index of string descriptor of serial number
         USB_NUM_CONFIGURATIONS   //number of possible configurations
   };


//////////////////////////////////////////////////////////////////
///
///   start string descriptors
///   String 0 is a special language string, and must be defined.  People in U.S.A. can leave this alone.
///
///   You must define the length else get_next_string_character() will not see the string
///   Current code only supports 10 strings (0 thru 9)
///
//////////////////////////////////////////////////////////////////

//the offset of the starting location of each string.
//offset[0] is the start of string 0, offset[1] is the start of string 1, etc.
const char USB_STRING_DESC_OFFSET[]={0,4,58};

#define USB_STRING_DESC_COUNT sizeof(USB_STRING_DESC_OFFSET)

char const USB_STRING_DESC[]={
   //string 0
         4, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         0x09,0x04,   //Microsoft Defined for US-English
   //string 1
         58, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         'H',0,
         'o',0,
         'o',0,
         'l',0,
         'i',0,
         'g',0,
         'a',0,
         'n',0,
         ' ',0,
         'T',0,
         'e',0,
         'c',0,
         'h',0,
         'n',0,
         'o',0,
         'l',0,
         'o',0,
         'g',0,
         'i',0,
         'e',0,
         's',0,
         ',',0,
         ' ',0,
         'I',0,
         'n',0,
         'c',0,
         '.',0,
         ' ',0,
   //string 2
         46, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         'D',0,
         'u',0,
         'a',0,
         'l',0,
         ' ',0,
         'M',0,
         'o',0,
         't',0,
         'o',0,
         'r',0,
         ' ',0,
         'C',0,
         'o',0,
         'n',0,
         't',0,
         'r',0,
         'o',0,
         'l',0
         'l',0,
         'e',0,
         'r',0,
         ' ',0
};

//Function Prototypes
void setup();


//Define Physical Pinouts
#define M1_ENAB   PIN_A0
#define M1_DIR    PIN_A1
#define M1_CLK    PIN_A2
#define M2_CHANA  PIN_A4
#define M2_ENAB   PIN_A5
#define M1_HMSNS  PIN_B0
#define M2_HMSNS  PIN_B1
#define M2_CHANB  PIN_C0
#define M2_PWM    PIN_C2
#define DEBUG_LED PIN_C7

#define TRIS_WORD_A  0b00010000
#define TRIS_WORD_B  0b00000111
#define TRIS_WORD_C  0b00000001

#define MAX_COMMAND_STRING_LENGTH            20
#define RETURN_MESSAGE_STRING_LENGTH         50

#define DC_SERVO                    '2'
#define STEPPER                     '1'

#define MAX_PWM_FORWARD             500
#define MAX_PWM_BACKWARD            0
#define PWM_STOPPED                 (MAX_PWM_FORWARD/2)
#define TIMER_2_PERIOD              (MAX_PWM_FORWARD/4)

#define AT_HOME                     1
#define NOT_AT_HOME                 0


char ReturnMessage[RETURN_MESSAGE_STRING_LENGTH];
char CommandString[MAX_COMMAND_STRING_LENGTH];

int1
res;

unsigned int8
t0con_reg,
t1con_reg;

signed int8
i;

unsigned int16
PWMDutyCyc,
timer0_read,
timer1_read;

signed int32
UpCount,
DnCount,
T0HiWord,
T1HiWord;

#ENDIF

_________________
Don't ever stop learning...
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Sep 07, 2007 12:34 pm     Reply with quote

That's not a short test program.
tatokash



Joined: 08 Aug 2007
Posts: 6

View user's profile Send private message

PostPosted: Fri Sep 07, 2007 1:02 pm     Reply with quote

Sorry.

If I could get away without the USB stuff it'd be shorter.

Any thoughts?
_________________
Don't ever stop learning...
kevcon



Joined: 21 Feb 2007
Posts: 142
Location: Michigan, USA

View user's profile Send private message

PostPosted: Fri Sep 07, 2007 1:11 pm     Reply with quote

Try disabling the 16bit reads and writes, the compiler turns them on by default.

Code:


#pragma byte T1CON = getenv( "SFR:T1CON" )
#pragma bit T1RD16 = T1CON.7


setup_timer_1( T1_EXTERNAL | T1_DIV_BY_1 );

T1RD16 = 0;

ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Sep 07, 2007 1:46 pm     Reply with quote

The timer 1 problem:
Reading a 16 bit timer on an 8 bit processor is always a bit difficult because of possible timer overflows in between reading the individual bytes. Microchip solved this by adding a buffer register for the Timer1_high byte. The buffer register is transered to or from the timer1_high byte on each access of the low byte. This process is described in more detail in the datasheet.

Your test1 and test2 are failing because you are accessing the timer high byte first while this should have been the second byte to access.

Test0 for timer1 is using the original CCS supplied functions which are reading the correct sequence.
kevcon



Joined: 21 Feb 2007
Posts: 142
Location: Michigan, USA

View user's profile Send private message

PostPosted: Fri Sep 07, 2007 2:29 pm     Reply with quote

That may be true, but either it doesn't work or the compiler is doing something goofy.

The code in the while loop never sends anything to hyper terminal with 16bit reads enabled, but it does when 16bit reads are disabled.

CCS version 4.038
18F65J10

Code:

#include "..\default.h"

#pragma use rs232( stream = COMPORT, baud = 2,400, UART2, parity = N, BITS = 8 )



#pragma byte T1CON = getenv( "SFR:T1CON" )
   #pragma bit T1RD16 = T1CON.7




void main( void )
{
   unsigned int16 abc;
   delay_ms( 500 );

   fprintf( COMPORT, "\x1B[2JBoard Ready at " );
   fprintf( COMPORT, __DATE__ );
   fprintf( COMPORT, "   " );
   fprintf( COMPORT, __TIME__ );


   set_timer1( 0 );

   setup_timer_1( T1_EXTERNAL | T1_CLK_OUT | T1_DIV_BY_1 );

//   T1RD16 = 0;

   while( 1 ) {

      abc = get_timer1( );


      if ( abc > 0xff ) {
         fprintf( COMPORT, "%Lu\n\r", abc );

      }
   }

}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Sep 07, 2007 3:56 pm     Reply with quote

Kevcon,
I don't have hardware with an external clock source on Timer1 so I can't check your code.

In v4.038 I changed the clock source to internal and the code did run without problems in the simulator. Both with and without the 16bit reads enabled.

Could you try to see if things improve when the external clock is synchronized? That is, set T1_EXTERNAL_SYNC.
Ttelmah
Guest







PostPosted: Sat Sep 08, 2007 3:18 am     Reply with quote

It'll be interesting if the chip is revision A3.
This has a hardware fault when 16bit mode is enabled, where the high byte does not update when the low byte is read...

Best Wishes
tatokash



Joined: 08 Aug 2007
Posts: 6

View user's profile Send private message

PostPosted: Mon Sep 10, 2007 6:36 am     Reply with quote

All,

Clearing that bit helped in all three scenarios. I guess I had assumed the compiler would do that automatically if I used the built in functions. Doh!


Ttelmah, how do I tell if the die is rev A3 or not? Part and serial number off the chip are as follows:

18F2550-I/SO with an e3 in a circle after
0639442

Thanks to all!
_________________
Don't ever stop learning...
kevcon



Joined: 21 Feb 2007
Posts: 142
Location: Michigan, USA

View user's profile Send private message

PostPosted: Mon Sep 10, 2007 6:59 am     Reply with quote

Clearing the SYNC bit helped in my situation as per the ERRATA for my chip.

Silly me too for thinking the compiler would handle it correctly, I should know better by now.


tatokash,

When you connect a porgrammer or ICD to the chip it should tell you what revision the chip is. There is a table on the first page of the errata sheets that tells what revisions are covered in each sheet.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group