This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Limitation of the compiler or what???

Hey folks,

I have a problem really interesting here. My program is really simple, I have just to read some information from analog inputs and send them throught CAN bus. I am using the microcontroller 167.

The source of the main function is showed on next:

void main(void)
{
  ubyte a, b, c, d, e, f, g, h;
  uword Gas = 0;
  uword Brake = 0;

  MAIN_vInit();

  while (1) {      /* loop forever*/

    Gas = ADC_ReadChannel(0);
    Gas = Gas & 0x3ff;
    a = LOWER_BYTE(Gas);
    b = UPPER_BYTE(Gas);

    Brake = ADC_ReadChannel(1);
    Brake = Brake & 0x3ff;
    c = LOWER_BYTE(Brake);
    d = UPPER_BYTE(Brake);

    while ( !CAN1_ubRequestMsgObj(1) );

    CAN1_vLoadData(1,0,a);
    CAN1_vLoadData(1,1,b);
    CAN1_vLoadData(1,2,c);
    CAN1_vLoadData(1,3,d);
    CAN1_vTransmit(1);
  }
} //  End of function main

So, when I test the program in the target hardware, the information that I read in CAN network (I have a monitor program in my PC connected in the CAN net) is supposed to show what I am reading from the analog inputs.

Well, when I read only one analog input and send by CAN, the program work well. But if I am reading two of analong inputs (as in the source code showed) and send these information by CAN, the ouptut comes wrong, always comes like 0xFF. I checked if there is a problem in the CAN drivers, but there is not. The problem is a simple basic operation of bits manipulation. How is it possible?

As I commented, if I commented the lines concerned with Brake analog input, for example, the program works.

//    Brake = ADC_ReadChannel(1);
//    Brake = Brake & 0x3ff;
//    c = LOWER_BYTE(Brake);
//    d = UPPER_BYTE(Brake);
//    CAN1_vLoadData(1,2,c);
//    CAN1_vLoadData(1,3,d);

Could someone explain me why is that? THere is some limitation on the compiler? Looks like a problem in the ocmpiler!

I am using DAvE to generate the drivers for CAN and ADC.

I am looking forward to hearing from someone!

Parents
  • I am not sure what version of Dave you are using to generate the function "CAN1_vLoadData". Have you changed it?

    In the version I have the function is:

    void CAN1_vLoadData(ubyte ubObjNr, ubyte *pubData);
    

    You need to provide more details as to what the code looks like in the functions or macros before I would say it is a compiler issue.

Reply
  • I am not sure what version of Dave you are using to generate the function "CAN1_vLoadData". Have you changed it?

    In the version I have the function is:

    void CAN1_vLoadData(ubyte ubObjNr, ubyte *pubData);
    

    You need to provide more details as to what the code looks like in the functions or macros before I would say it is a compiler issue.

Children
  • Yes, I changed a little bit, because I couldn't use arrays or pointers! Another big problem!!!
    I had to pass byte per byte, so the function CAN1_vLoadData() works.

    For example, in the main function I have created a vector like that:

    ubyte buffer[2] = {0x01,0x02};
    
    CAN1_vLoadData(1,buffer);
    

    The message that was send throught CAN bus was 0xFF, 0xFF.
    But, if inside the CAN1_vLoadData I define directly the value for the data structure.

    CAN1_OBJ[ubObjNr - 1].Data[0] = 0x01;
    CAN1_OBJ[ubObjNr - 1].Data[1] = 0x02;
    

    That works! Therefore, I changed the function to receive byte per byte. I couldn't work with arrays or pointers!! I have some experience with C and anwyay, I didn't get any compiler errors.

    Well, I just say that it is a compiler problem, because I couldn't find another explanation for that!
    And I don't know what should I provide more as information. I have programmed almost nothing, just calling the functions from DAvE.

    Is there some relevant information that I should provide?
    Thank you in advance!

  • The function CAN1_vLoadData doesn't change the "dlc" value so needs to match the number of valid bytes of data you have. For getting started you could just leave it set to eight.

    Here is your example where you sould see 0x23,0x01,0x56,0x03 as the first four data bytes.

    #include <reg167.h>
    #include "can.h"
    
    typedef unsigned char  ubyte;    // 1 byte unsigned; prefix: ub
    typedef signed char    sbyte;    // 1 byte signed;   prefix: sb
    typedef unsigned int   uword;    // 2 byte unsigned; prefix: uw
    typedef signed int     sword;    // 2 byte signed;   prefix: sw
    typedef unsigned long  ulong;    // 4 byte unsigned; prefix: ul
    typedef signed long    slong;    // 4 byte signed;   prefix: sl
    
    struct can1_obj
    {
      uword  MCR;       // Message Control Register
      uword  UAR;       // Upper Arbitration Register
      uword  LAR;       // Lower Arbitration Register
      ubyte  MCFG;      // Message Configuration Register
      ubyte  Data[8];   // Message Data 0 .. 7
      ubyte  Customer;  // Reserved for application specific data
    };
    
    #define CAN1_OBJ ((struct can1_obj volatile *) 0xEF10)
    
    typedef struct
    {
       ubyte ubMsgCfg;   // 8-bit Message Configuration Register
       ulong ulArbitr;   // standard (11-bit)/extended (29-bit) identifier
       ubyte ubData[8];  // 8-bit Data Bytes
       ubyte ubUser;     // for application specific states
    }TCAN1_Obj;
    
    TCAN1_Obj CAN_data;
    
    void CAN1_vInit(void) {
      C1CSR          =  0x0041;      // set CAN1 INIT and CCE
      C1BTR          =  0x3449;      // set CAN1 bit timing register
      C1GMS          =  0xFFFF;      // set CAN1 global mask short register
      C1UGML         =  0xFFFF;      // set CAN1 upper global mask long register
      C1LGML         =  0xF8FF;      // set CAN1 lower global mask long register
      ///  - message object 1 is valid
      CAN1_OBJ[0].MCR  =  0x5695;    // set CAN1 message control register
      CAN1_OBJ[0].MCFG =  0x88;      // set CAN1 message configuration register
      CAN1_OBJ[0].UAR  =  0x0000;    // set CAN1 upper arbitration register
      CAN1_OBJ[0].LAR  =  0x0000;    // set CAN1 lower arbitration register
      DP4  = (DP4  & ~(uword)0x0040) | 0x0040;    //set direction register
      ///  - reset CCE and INIT
      C1CSR          =  0x0000;      // set CAN1 control satatus register
    }
    
    void CAN1_vLoadData(ubyte ubObjNr, ubyte *pubData) {
      ubyte i;
    
      CAN1_OBJ[ubObjNr - 1].MCR = 0xfaff;  // set CPUUPD and NEWDAT
    
      for(i = 0; i < (CAN1_OBJ[ubObjNr - 1].MCFG & 0xf0) >> 4; i++) {
        CAN1_OBJ[ubObjNr - 1].Data[i] = *(pubData++);
      }
    
      CAN1_OBJ[ubObjNr - 1].MCR = 0xf7ff;  // reset CPUUPD
    }
    
    void CAN1_vTransmit(ubyte ubObjNr) {
      CAN1_OBJ[ubObjNr - 1].MCR = 0xe7ff;  // set TXRQ,reset CPUUPD
    }
    
    void main(void) {
      uword Gas = 0;
      uword Brake = 0;
    
      CAN1_vInit();
    
      Gas = 0x0123;
      Gas = Gas & 0x3ff;
    
      CAN_data.ubData[0] = (ubyte) (Gas);
      CAN_data.ubData[1] = (ubyte) (Gas >> 8);
    
      Brake = 0x1356;
      Brake = Brake & 0x3ff;
    
      CAN_data.ubData[2] = (ubyte) (Brake);
      CAN_data.ubData[3] = (ubyte) (Brake >> 8);
    
      CAN1_vLoadData(1,&CAN_data.ubData[0]);
      CAN1_vTransmit(1);
    
      for(;;);
    }
    

  • I compiled the peace of code from the last post, I got the same problem (I read everything as 0xFF). I cannot work with ARRAYS or POINTERS. That is unbelievable. I changed the source to prove that:

    void CAN1_vLoadData(ubyte ubObjNr, ubyte pos, ubyte pubData) {
    
      CAN1_OBJ[ubObjNr - 1].MCR = 0xfaff;  // set CPUUPD and NEWDAT
    
        CAN1_OBJ[ubObjNr - 1].Data[pos] = pubData;
    
      CAN1_OBJ[ubObjNr - 1].MCR = 0xf7ff;  // reset CPUUPD
    }
    
    void CAN1_vTransmit(ubyte ubObjNr) {
      CAN1_OBJ[ubObjNr - 1].MCR = 0xe7ff;  // set TXRQ,reset CPUUPD
    }
    
    void main(void) {
      uword Gas = 0;
      uword Brake = 0;
    
      CAN1_vInit();
    
    //  Gas = 0x0123;
    //  Gas = Gas & 0x3ff;
    //  CAN_data.ubData[0] = (ubyte) (Gas);
    //  CAN_data.ubData[1] = (ubyte) (Gas >> 8);
    
      Brake = 0x1356;
      Brake = Brake & 0x3ff;
      CAN_data.ubData[2] = (ubyte) (Brake);
      CAN_data.ubData[3] = (ubyte) (Brake >> 8);
    
      CAN1_vLoadData(1,0,0x01);
      CAN1_vLoadData(1,1,0x02);
      CAN1_vLoadData(1,2,CAN_data.ubData[2]);
      CAN1_vLoadData(1,3,CAN_data.ubData[3]);
      CAN1_vTransmit(1);
      for(;;);
    }
    

    The rest of the source, I kept the same. In this case, I can read {0x01 0x02 0xFF 0xFF}, which makes sense!

    Is there an explanation for that? Is there any FLAG that I have to pass to the Compiler??

  • I am not familiar with DAvE, but there are two issues:
    You said that you modified

    void CAN1_vLoadData(ubyte ubObjNr, ubyte *pubData);
    

    as it didn't work. Well, as far as I can see, the message length is set to 8 in CAN1_vInit():

    CAN1_OBJ[0].MCFG =  0x88;
    

    As the buffer in your example has only a length of 2

    ubyte buffer[2] = {0x01,0x02};
    CAN1_vLoadData(1,buffer);
    

    you surely have undefined results for bytes 3 .. 8 when using the original version of CAN1_vLoadData().
    The other issue is about setting CPUUPD / NEWDAT in your modified function. I am not sure if everything works well if you modify these bits for every byte to be loaded.
    Anyway, I don't think that your problem has anything to do with the compiler, but merely with providing proper values to all affected CAN registers.

  • Hey folks,

    I found the problem. I have to declare the variables with "SDATA".

    TCAN1_Obj sdata CAN_data;
    

    So, I can manipulate and read correctly. But I couldn't understand why! I just checked that in the possible memory types.
    http://www.keil.com/support/man/docs/c166/c166_le_sdata.htm