Hi all,
I am very new to C programming and I need your help.
Can anyone tell me how can I transmit a frame in C programming?
Printable View
Hi all,
I am very new to C programming and I need your help.
Can anyone tell me how can I transmit a frame in C programming?
Transmit to what? What sort of Frame?
What have you tried so far?
--
Mats
I have a frame format which is as follows:
start char 'S'
device address '0x4E'
write command '0xFE'
no of bytes (any no)
actal bytes
stop char 'P'.
How can I combine all this?
So, what type of device is this for (Ethernet, Serial, I2C, proprietary, or ...), and what is the hardware (e.g. PC or some specific single-board computer, perhaps?) and software environment (OS, Compiler, libraries, etc) you are using?
--
Mats
I need to communicate to an I2C using a bridge chip. The controller is XC164CM.
The bridge chip SC18IM700 is like an interface which helps the host to communicate to an I2C. The format which I have sent before is predefined by the bridge chip.
I am usiing ASC1 port for communication. The initial structure has been done using DAvE.
I am using the XC164CM starter kit by infineon technologies
Ok, and how far have you got so far?
--
Mats
The command I have to use to send the 'S' char is ASC1_vSendData ('S');
I have done that, and it works. I am using a scope meter to check the status on the pins of the hardware. This char is being sent but I am not able to receive it.
Secondly, its ok if I cant receive it back. I need to send the frame format i posted earlier.
Initially, I was just sending a character to check if the bridge chip works. I can confirm that it works. The SC18IM700 communicates with the host using MAX 3227E. For the moment, don't consider the I2C. Now, I know that SC18IM700 is receiving data from ASC1 TX but, ASC1 does not receive the data back from SC18IM700.
I have pasted the functions below. Can you tell me how can I read the 'S' char using ASC1_uwGetData function?
Code://****************************************************************************
// @Function void ASC1_vSendData(uword uwData)
//
//----------------------------------------------------------------------------
// @Description This function writes a send data initialization word into
// the transmit buffer register.
//
// Note:
// In a multiprocessor system the master with this function
// has the possibility to send data to the selected slave. To
// achieve this, the 9th bit must set on zero.
//
//----------------------------------------------------------------------------
// @Returnvalue None
//
//----------------------------------------------------------------------------
// @Parameters uwData:
// Data to be send
//
//----------------------------------------------------------------------------
// @Date 25/11/2008
//
//****************************************************************************
// USER CODE BEGIN (SendData,1)
void ASC1_send()
{
ASC1_vSendData ('S');
}
void ASC1_vSendData(uword uwData)
{
ASC1_TBIC_IR = 0; // reset transmit buffer interrupt request
ASC1_TBUF = uwData; // load transmit buffer register
while (ASC1_TBIC_IR == 0);//wait till transmission finish
} // End of function ASC1_vSendData
//****************************************************************************
// @Function uword ASC1_uwGetData(void)
//
//----------------------------------------------------------------------------
// @Description This function reads out the content of the receive buffer
// register which contains the received data.
//
//----------------------------------------------------------------------------
// @Returnvalue data that has been received
//
//----------------------------------------------------------------------------
// @Parameters None
//
//----------------------------------------------------------------------------
// @Date 25/11/2008
//
//****************************************************************************
// USER CODE BEGIN (GetData,1)
// USER CODE END
uword ASC1_uwGetData(void)
{
return(ASC1_RBUF); // return receive buffer register
} // End of function ASC1_uwGetData
So, can you, using the scope, observe data being sent from the SCM?
--
Mats
No. I tried using the scope on TX pin of SCM but I am not getting anything back
I guess u r right. Since its a bridge chip, maybe it needs something before sending something. Thats where the frame i mentioned comes in. Its a frame that sends data from host to I2C using the bridge chip. Thats the point where I am stuck up. I logically know what I am supposed to do, but I am not able to write it in C.
The way I would do it would be to package up the entire frame into an array of bytes, tracking the length of it. Then send the package using a for-loop that calls vSendData for each byte.
If you have no idea how to do that, then I suggest you get your C book out.
--
Mats
I agree with you. Thats what I am trying to do.
I will get back to you.
Thanks a lot for your help.
Hello again everyone !!!
Following is the frame which I am transmitting (please refer to previous posts for details). Can anyone tell me if it is correct?
I appreciate your help.Code:char send[6] = {0x53,0x4E,0x32,0x46,0x48,0x50};
for (i=0;i<6;i++)
{
data = send[i];
ASC1_vSendData (data);
}
Thank you.
I would do:
Versus your previous post, you are missing an 0xFE at the third byte, and I'm not sure you want an ASCII '2' or the value 0x02 in the length field - if it was my protocol, I would probably use a binary value, as that allows more than 1-9 bytes of message - but if the message is always very short, the ascii value is better, I suppose.Code:char send[6] = {'S',0x4E,0x32,'G','H', 'P'};
I also wouldn't use an extra variable before passing it to send. But that is much elss of an issue.
--
Mats
If I have to send two bytes, can i use '0x02' as the length value and still send
'0x46' and '0x48 as the actual bytes?
I have no idea - the length is part of the protocol, and I do not know what your protocol specifies. It just "feels wrong" in relation to other protocols that I've seen. But it's not unheard of to send the size as a printable character - it's just limiting the number of bytes you can send to 0..9 [for one digit].
--
Mats
Please bear with me on this since I am fairly new to all this.
Instead of using an array, can I use a structure which will allow me to define different data types the way i want?
If you do that and you can only transmit one byte at a time, you won't be able to use the for loop because you will have to refer to the struct members individually, which they will all be (the same as) chars anyway (so what's the point?) You'll have gone from something appropriately simple to something with unnecessary complications.
Aside from MK27's answer, it is also difficult to have a variable payload, since the payload is in the middle of the packet, not at the end.
--
Mats
Thanks both of you.
As matsp said before about using a binary number in the length field, how can i declare a binary number in the array?
All numbers in computers are BINARY. What I mean by that is the value 0x02 or 2 (whichever you prefer) - it's the same value, rather than '2' or 0x32 (again, you choose which you use - as long as we are dealing with ASCII/ANSI compliant character sets, they are identical).
C does not support "binary" in source code as standard. A few compilers, particularly for embedded use have extensions, so you can write something like 0b0000010 to describe the value 2 - but it's still stored exactly the same way whether you write 2, 0x02 or any other format that the compiler supports.
--
Mats
I would probably write a function that takes the payload and length, along with a buffer (and perhaps buffer-size so you can DETECT that your payload and framing doesn't fit, if the buffer isn't big enough).
Then just fill in the start of the buffer, use a loop to copy the payload, and then mark the end with a 'P'. Something like this would be the calling code:
I'm leaving it to you to define the function itself.Code:char buffer[256];
const char *payload = "abcd";
BuildFrame(payload, strlen(payload), buffer, sizeof(buffer));
--
Mats
Hello again !!!
Well, as matsp had suggested, I have succeeded in transmitting the frame.
I need help in something else now.
I need to configure the General Purpose Input/Output (GPIO) pin of SC18IM700. I need to pull it low.
How do I define it in C?
Thanks for your help.
http://www.nxp.com/acrobat/datasheets/SC18IM700_2.pdf
It seems like writing an 'O' followed by the relevant data for the GPIO port will do the job. Of course, you may have to configure the GPIO port first so that the pin is an output. You need to set PortConf0 or PortConf1 to get that set right.
--
Mats
You need to set it up according to the table in section 9.2.2, by writitng the corresponding bits in the PortConf1. To do that, you need to use the 'W' command.
--
Mats
The description is a big vague, but I expect you send the value 0x02, then the value you want to set the register to, and then a 'P' to end the message.
--
Mats
Well, in this case, "register" is just a number you send to the other processor, so you can of course use #define, const or enum to declare a constant equivalent of the register number. That will make it more symbolic, but it will not change what is actually sent out from your processor.
--
Mats
Ok, thanks. Well I figured out a while before that the function 'ASC1_vSendData()' doesnt send anything other than the ASCII characters. I used the ASC0 port to display contents of the array on the hyperterminal. I sent an arraybut it just displays WP.Code:{'W',0x02,0x08,'P'}
Yes, and unless you have a better way to "see" what you are doing, such characters will be INVISIBLE - even of 0x02 is visible (it possibly is - on a PC it's a smiley face, I think), 0x08 will be a backspace and go back so that the NEXT character written writes over the 0x02.
At this point, you may want to find a program that can log from a serial port to a file or some such, so that you can see what is ACTUALLY going on. I've written applications to do this more than once - including one that logged the traffic between a ISDN modem and it's controlling computer in both directions at once when browsing a web-site. Unfortunately, it was written for OSE, which is an embedded OS, so it's probably not much use to anyone here (should I find the source code somewhere).
--
Mats
Hello again !!!
Just to check that my function is running fine, I am now using the hyperterminal and ASC0 port.
My code is as follows:
When I run the code, it only displays 'WP' and doesn't consider 'N'.Code:void ASC0_send()
{
int i,data = 0;
unsigned char sd[] = {'W','N,'P'};
for(i=0;i<3;i++)
{
data = sd[i];
ASC0_vSendData (data);
}
}
Am I missing something here?
Is your ASC0_vSendData() not waiting if the port is busy, perhaps? Otherwise I don't know.
--
Mats
This is the actual full ASC0_VsendData function. Does it make more sense now?Code://****************************************************************************
// @Function void ASC0_vSendData(uword uwData)
//
//----------------------------------------------------------------------------
// @Description This function writes a send data initialization word into
// the transmit buffer register.
//
// Note:
// In a multiprocessor system the master with this function
// has the possibility to send data to the selected slave. To
// achieve this, the 9th bit must set on zero.
//
//----------------------------------------------------------------------------
// @Returnvalue None
//
//----------------------------------------------------------------------------
// @Parameters uwData:
// Data to be send
//
//----------------------------------------------------------------------------
// @Date 26/11/2008
//
//****************************************************************************
// USER CODE BEGIN (SendData,1)
void ASC0_send()
{
int i,data = 0;
unsigned char sd[] = {'W','O','P'};
for(i=0;i<3;i++)
{
data = sd[i];
ASC0_vSendData (data);
}
}
// USER CODE END
void ASC0_vSendData(uword uwData)
{
ASC0_TBIC_IR = 1; // reset transmit buffer interrupt request
ASC0_TBUF = uwData; // load transmit buffer register
} // End of function ASC0_vSendData
Looks like you need some sort of "wait for completion" before you send the next data item. Since I have no idea what OS you are using, etc, I can't really comment on how you should go about doing that.
I expect this would mean that you get an interrupt at some point later, when the transmit is "ready" to send the next char.Code:ASC0_TBIC_IR = 1; // reset transmit buffer interrupt request
--
Mats
I managed to display 'WNP' entirely on the hyperterminal. The problem was with the predefined ASC0_vSendData function. New function is as follows:
This code prints 'WNP' properly now.Code:void ASC0_vSendData(uword uwData)
{
ASC0_TBIC_IR = 0; // reset transmit buffer interrupt request reset=0; set=1
ASC0_TBUF = uwData; // load transmit buffer register
while (ASC0_TBIC_IR == 0); //wait till transmission finish
} // End of function ASC0_vSendData
Thanks for your help.
That is a possible solution, but I would ask someone who knows more about the OS/runtime environment, because there may be a better way to "wait for an interrupt" than to poll the bit for the interrupt control.
--
Mats
If you have a RTOS that supports multiple tasks/processes/threads, then you waiting like that will eat time off other tasks(etc) that may want to run. If the processor has power-management it may want to "go to sleep" if there's no activity going on, so again, your solution will affect the power-consumption in that case.
--
Mats
I would agree, that waiting till the transmit queue is ready to accept more data is a bit overkill. Halting the OS a bit to wait is much more efficient, but a bit slower. Coming up with an optimum wait in ms's will require some testing.
This might be a stupid remark but why would you want to learn c programming when you can learn C++..... Isn't C++ better then C ? I'm really not sure so don't attack me :)
Well, in this case, the target system is a single-board micro-computer, so it is not necessarily a good target for the heavy tools of C++. And the code being discussed here would be marginally different either way - or do you know something that I do not know in the particular project?
--
Mats
Hello again !!!!
I have a question. If I have to set any GPIO pin of a particular IC without the bridge chip(in this case,without using the W command) how can I do it?
I have absolutely no idea. You'd have to talk to someone who knows that chip.
--
Mats
Hello !!!
I am transmitting the following data via ASC1 port.
I know that the data is being sent to the hardware since I can view it using a Scopemeter.Code:void ASC1_send()
{
ASC1_vSendData ('W'); //write to internal reg command
ASC1_vSendData (2); //push pull o/p config
ASC1_vSendData (8); //set portconf1 to 0x08
ASC1_vSendData ('P'); //stop
ASC1_vSendData ('O'); //write to GPIO
ASC1_vSendData (0); //set it to 0
ASC1_vSendData ('P'); //stop
ASC1_vSendData ('S'); //start
ASC1_vSendData (160); //device address=A0=>160 in decimal
ASC1_vSendData (07); //data
ASC1_vSendData (11);
ASC1_vSendData (97);
ASC1_vSendData (80);
ASC1_vSendData (00);
ASC1_vSendData (40);
ASC1_vSendData (55); //data
ASC1_vSendData (250); //data
ASC1_vSendData ('S');
ASC1_vSendData (161);
ASC1_vSendData (07);
ASC1_vSendData ('P');
}
void ASC1_vSendData(uword uwData)
{
ASC1_TBIC_IR = 0; // reset transmit buffer interrupt request set = 1;
ASC1_TBUF = uwData; // load transmit buffer register
while (ASC1_TBIC_IR == 0);//wait till transmission finishes
} // End of function ASC1_vSendData
I want to introduce a stop condition after the last char ie ASC1_vSendData('P') is sent. How can I do it?
Hello!!!
I want to generate a simple counter which will give me a certain delay eg 500msec in between 2 bytes of data that i am sending. How can I generate the counter??
Thanks in advance for your help.
So use delay(500); that will give you at least 1/2 a second. Typically more, with Windows.
There is no visible counter to delay(), however.