How do I build up a LIN message and send it out in CAPL - bus

I am a beginner in CAPL script. I am writing a script to send a 8 byte message with a frame id (PID). When i run the script in canoe, ECU does not give a response.Every thing in the setup and database is correct. There is a problem in script. Below is the script.
/*#!Encoding:1252*/
variables
{
linmessage 0x11 Request;
linmessage 0x25 Response;
linmessage 0x01 Initiate_wake_up;
byte WakeUpFrame = 0x3E;
byte Request_Header = 0x11;
byte Response_Header = 0x25;
}
void Util_SendHeader(byte frameID)
{
Request.MsgChannel = 1;
Request.ID = frameID;
Request.RTR=1;
output(Request);
}
void Wake_Up_Frame()
{
Util_SendHeader (WakeUpFrame);
Request.byte(0)=0x00;
Request.byte(1)=0x00;
Request.byte(2)=0x00;
Request.byte(3)=0x00;
Request.byte(4)=0x00;
Request.byte(5)=0x00;
Request.byte(6)=0x00;
Request.byte(7)=0x00;
Request.rtr=0;
output(Request);
}
on key 'q'
{
Wake_Up_Frame();
Request.byte(0) = 0x00;
Request.byte(1) = 0x0A;
Request.byte(2) = 0x00;
Request.byte(3) = 0x00;
Request.byte(4) = 0x00;
Request.byte(5) = 0x00;
Request.byte(6) = 0x00;
Request.byte(7) = 0x00;
Util_SendHeader (Request_Header);
Request.rtr=0;
output(Request);
Util_SendHeader (Response_Header);
}
Please help me.

To send a LIN message, two output() calls are required: 1-st with .rtr=0 and second with .rtr=1.
The first one schedules message data for transmission. The second one triggers the transmission.
If, instead of second output(), some external master sends the message header on the LIN bus, and the header ID matches the ID of scheduled message, the tool will transmit the message (acting as a slave).
To receive a message from slave, only the second output() is required. It will transmit the message header on LIN bus. Any slave that has a matching message ready (same ID) will transmit the message data.

Related

How to receive messages via wifi while running main program in ESP32?

Ive incorporated multiple features i want in a microcontroller program (ESP32 Wroom32) and needed some advice on the best way to keep the program running and receive messages while it is running.
Current code:
//includes and declarations
setup()
{
//setup up wifi, server
}
main(){
WiFiClient client = server.available();
byte new_command[40];
if (client) // If client object is created, a connection is setup
{
Serial.println("New wifi Client.");
String currentLine = ""; //Used to print messages
while (client.connected())
{
recv_byte = client.read();
new_command = read_incoming(&recv_byte, client); //Returns received command and check for format. If invalid, returns a 0 array
if (new_command[0] != 0) //Checks if message is not zero, None of valid messages start with zero
{
execute_command(new_command);
//new_command is set to zero
}
}//end of while loop
}//end of if loop
}
The downside of this is that the ESP32 waits till the command is finished executing before it is ready to receive a new message. It is desired that the ESP32 receive commands and store them, and execute it at its own pace. I am planning to change the current code to receive a messages while the code is running as follows:
main()
{
WiFiClient client = server.available();
byte new_command[40];
int command_count = 0;
byte command_array[50][40];
if (command_count != 0)
{
execute_command(command_array[0]);
//Decrement command_count
//Shift all commands in command_array by 1 row above
//Set last executed command to zero
}
}//end of main loop
def message_interrupt(int recv_byte, WiFiClient& running_client)
{
If (running_client.connected())
{
recv_byte = running_client.read();
new_command = read_incoming(&recv_byte, running_client); //Returns received command and check for format. If invalid, returns a 0 array
//add new command to command_array after last command
//increment command_count
}
}
Which interrupt do I use to receive the message and update the command_array ? https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html Doesnt mention any receive/transmit events. I couldnt find any receive/transmit interrupt either or maybe I searched for the wrong term.

Command "InListPassiveTarget" of the PN532 device returns only one ACK and nothing else

I have managed to communicate with the PN532 device through a microcontroller (RS232). I get it out of the low power mode, I get the firmware version and the general status.
Now I want to read a MiFare type tag (ISO / IEC14443) and the frame I send is the following:
transmissionBuffer[0] = 0x00;
transmissionBuffer[1] = 0x00;
transmissionBuffer[2] = 0xFF;
transmissionBuffer[3] = 0x04;
transmissionBuffer[4] = 0xFC;
transmissionBuffer[5] = 0xD4;
transmissionBuffer[6] = 0x4A ;
transmissionBuffer[7] = 0x01;
transmissionBuffer[8] = 0x00;
transmissionBuffer[9] = 0xE1;
transmissionBuffer[10] = 0x00;
And the frame that the PN532 answers is:
receptionBuffer[0] = 0x00;
receptionBuffer[1] = 0x00;
receptionBuffer[2] = 0xFF;
receptionBuffer[3] = 0x00;
receptionBuffer[4] = 0xFF;
receptionBuffer[5] = 0x00;
I want to indicate that I perform a procedure in the reception of data from the MCU which consists of a timer that is reset every time a byte arrives from the PN532 and when no more bytes arrive, the timer overflows and it is assumed that the frame has arrived complete.
That way in a single package I get the ACK more the answer.
To rule out that the response to the "InListPassiveTarget" command takes more time than the timer, I have tried up to 20 seconds and only the ACK arrives for that command.
For the others that I mentioned at the beginning, there is no problem.
Beforehand I appreciate any suggestions or comments.
Thanks

Transmission using SPI in AVR

When will SPIF bit in SPSR will reset after transmission of data
Suppose
void SPITransmit(uint8_t data)
{
SPDR = data;
while(!(SPSR & (1<<SPIF)));
}
After transmission SPIF will set and how to reset this bit for reception.
With SPI, you don't get to choose whether you are sending or transmitting, you do both at the same time. So there is no need to "reset SPIF for reception". I believe the received data is available in the SPDR register after your loop terminates, but you should read the datasheet for your particular AVR to make sure.
Here is a function you could use to transmit and receive at the same time:
uint8_t SPITransmit(uint8_t data)
{
SPDR = data;
while(!(SPSR & (1<<SPIF)));
return SPDR;
}

Writing SSPBUF from variable in I2C slave protocol in PIC18

I am writing an I2C slave routine for PIC18F25K80 and I am stuck on a weird problem.
This is my routine:
void interrupt interruption_handler() {
PIE1bits.SSPIE = 0; // Disable Master Synchronous Serial Port Interrupt
if (PIR1bits.SSPIF != 1) {
//This is not I2C interruption;
PIE1bits.SSPIE = 1; // Enable Master Synchronous Serial Port Interrupt
return;
}
//Treat overflow
if ((SSPCON1bits.SSPOV) || (SSPCON1bits.WCOL)) {
dummy = SSPBUF; // Read the previous value to clear the buffer
SSPCON1bits.SSPOV = 0; // Clear the overflow flag
SSPCON1bits.WCOL = 0; // Clear the collision bit
SSPCON1bits.CKP = 1;
board_state = BOARD_STATE_ERROR;
} else {
if (!SSPSTATbits.D_NOT_A) {
//Slave address
debug(0, ON);
//Read address
address = SSPBUF; //Clear BF
while(BF); //Wait until completion
if (SSPSTATbits.R_NOT_W) {
SSPCON1bits.WCOL = 0;
unsigned char a = 0x01;
SSPBUF = a;//0x01 works //Deliver first byte
asm("nop");
}
} else {
if (SSPSTATbits.BF) {
dummy = SSPBUF; // Clear BF (just in case)
while(BF);
}
if (SSPSTATbits.R_NOT_W) {
//Multi-byte read
debug(1, ON);
SSPCON1bits.WCOL = 0;
SSPBUF = 0x02; //Deliver second byte
asm("nop");
} else {
//WRITE
debug(2, ON);
}
}
transmitted = TRUE;
SSPCON1bits.CKP = 1;
PIR1bits.SSPIF = 0;
PIE1bits.SSPIE = 1; // Enable Master Synchronous Serial Port Interrupt
}
}
It works like a charm if I set constant values on SSPBUF. For example, if you do:
SSPBUF = 0x01;
(...)
SSPBUF = 0x02;
I get the two bytes on the master. I can even see the wave forms of the bytes being transmitted on the oscilloscope. Quite fun!
But when I try to set SSPBUF using a variable like:
unsigned char a = 0x01;
SSPBUF = a;
I get zero on the master.
It is driving me crazy.
Some hypothesis I've discarded:
Watchdog timer is messing up interrupting in the middle of the protocol: It is not. It is disabled and the problem happens in both SSPBUF assignments
I need to wait until BF goes low to continue: I don't. AFAIK, you setup the SSPBUF, clear SSPIF, set CKP and return from interruption to take care of life in 4Mhz while the hardware send data in few Khz. It will interrupt you again when it finishes.
It makes no sense to me. How good it is if you cannot define an arbitrary value using a variable?
Please gurus out there, enlighten this poor programmer.
Thanks in advance.
It has something to do with how the compiler generates the code and some undocumented/unknown PIC restriction around SSPBUF (it is an special register anyway).
I found out that it works when the compiler uses movwf and does not work when the compiler uses movff.
I moved the question to another forum because I realized the audience there is more adequate.
You will find more details here:
https://electronics.stackexchange.com/questions/251763/writing-sspbuf-from-variable-in-i2c-slave-protocol-in-pic18/251771#251771
Try move declaration : "unsigned char a = 0x01;"
to the beginning of the function or try define it as volatile global variable.
take into accunte that SSPBUF is both read and write buffer.check if there are conditions that may cause I2C module to reset this buffer.

Core MIDI: when I send a MIDIPacketList using MIDISend() only the first packet is being sent

I am trying to send a MIDIPacketList containing two packets that describe controller position change message relating to a x-y style controller.
The function i'm trying to implement takes the an x and y position, and then creates the packets and sends them to the selected target device as follows:
- (void)matrixCtrlSetPosX:(int)posX PosY:()posY {
MIDIPacketList packetList;
packetList.numPackets = 2;
packetList.packet[0].length = 3;
packetList.packet[0].data[0] = 0xB0; // status: controller change
packetList.packet[0].data[1] = 0x32; // controller number 50
packetList.packet[0].data[2] = (Byte)posX; // value (x position)
packetList.packet[0].timeStamp = 0;
packetList.packet[1].length = 3;
packetList.packet[1].data[0] = 0xB0; // status: controller change
packetList.packet[1].data[1] = 0x33; // controller number 51
packetList.packet[1].data[2] = (Byte)posY; // value (y position)
packetList.packet[1].timeStamp = 0;
CheckError(MIDISend(_outputPort, _destinationEndpoint, &packetList), "Couldn't send MIDI packet list");
}
The problem I am having is that the program only appears to be sending out the first packet.
I have tried splitting the output into two separate MIDIPacketLists and two making two calls to MIDISend(), which does work, but I am sure that there must be something trivial I am missing out in building the midi packet list so that the two messages can be sent in one call to MIDISend(). I just cannot seem to figure out what the problem is here! Anyone here had experience doing this, or am I going about this the wrong way entirely?
Just declaring the MIDIPacketList doesn't allocate memory or set up the structure. There's a process to adding packets to the list. Here's a quick and dirty example:
- (void)matrixCtrlSetPosX:(int)posX PosY:(int)posY {
MIDITimeStamp timestamp = 0;
const ByteCount MESSAGELENGTH = 6;
Byte buffer[1024]; // storage space for MIDI Packets
MIDIPacketList *packetlist = (MIDIPacketList*)buffer;
MIDIPacket *currentpacket = MIDIPacketListInit(packetlist);
Byte msgs[MESSAGELENGTH] = {0xB0, 0x32, (Byte)posX, 0xB0, 0x33, (Byte)posY};
currentpacket = MIDIPacketListAdd(packetlist, sizeof(buffer),
currentpacket, timestamp, MESSAGELENGTH, msgs);
CheckError(MIDISend(_outputPort, _destinationEndpoint, packetlist), "Couldn't send MIDI packet list");
}
I adapted this code from testout.c found here

Resources