I need help in calculating modbus CRC check for function code 1. I.e read coil register. I have sample code for CRC check for function code 3 i.e holding register for analog input.
# Read Coil Status (FC=01)
## Request
This command is requesting the ON/OFF status of discrete coils # 20 to 56
from the slave device with address 17.
11 01 0013 0025 0E84
11: The Slave Address (17 = 11 hex)
01: The Function Code (read Coil Status)
0013: The Data Address of the first coil to read. (Coil 20 - 1 = 19 = 13 hex)
0025: The total number of coils requested. (coils 20 to 56 = 37 = 25 hex)
0E84: The CRC (cyclic redundancy check) for error checking.
Response
11 01 05 CD6BB20E1B 45E6
11: The Slave Address (17 = 11 hex)
01: The Function Code (read Coil Status)
05: The number of data bytes to follow (37 Coils / 8 bits per byte = 5 bytes)
CD: Coils 27 - 20 (1100 1101)
6B: Coils 35 - 28 (0110 1011)
B2: Coils 43 - 36 (1011 0010)
0E: Coils 51 - 44 (0000 1110)
1B: 3 space holders & Coils 56 - 52 (0001 1011)
45E6: The CRC (cyclic redundancy check).
Read Holding Registers (FC=03)
Request
This command is requesting the content of analog output holding registers # 40108 to
40110 from the slave device with address 17.
11 03 006B 0003 7687
11: The Slave Address (17 = 11 hex)
03: The Function Code (read Analog Output Holding Registers)
006B: The Data Address of the first register requested. (40108-40001 = 107 = 6B hex)
0003: The total number of registers requested. (read 3 registers 40108 to 40110)
7687: The CRC (cyclic redundancy check) for error checking.
Response
11 03 06 AE41 5652 4340 49AD
11: The Slave Address (17 = 11 hex)
03: The Function Code (read Analog Output Holding Registers)
06: The number of data bytes to follow (3 registers x 2 bytes each = 6 bytes)
AE41: The contents of register 40108
5652: The contents of register 40109
4340: The contents of register 40110
49AD: The CRC (cyclic redundancy check).
I am no issue for getting response for FC3. because i am sending properly the 2 byte address , but i dont know how can i send single byte and modify crc function for FC1 ->read coil register
Discription of read coil register
unsigned int crc_fn(unsigned char *dpacket,unsigned int len) { // CRC Function(Error calcualtion)
unsigned int crc = 0xffff,poly = 0xa001;
unsigned int i=0;
for(i=0; i<len; i++) {
crc^= dpacket[i];
for(j=0; j<8; j++) {
if(crc & 0x01) {
crc >>= 1;
crc ^= poly;
} else
crc >>= 1;
}
}
return (crc);
}
CRC is normally appended to a message most significant byte first. You need to swap two lines of code, sending the high order byte of the 16 bit crc before the low order byte. Try this change:
Serial_1_Send_byte((unsigned char)(crc1>>8));
Serial_1_Send_byte((unsigned char)crc1);
Related
I would like to ask a question about how to write inline assembly code for Store-Conditional instruction in RISC-V. Below is some brief background (RISCV-ISA-Specification on page 40, section 7.2):
SC writes a word in rs2 to the address in rs1, provided a valid reservation still exists on that address. SC writes zero to rd on success or a nonzero code on failure.
The instruction that we will be focusing on is SC.D - store-conditional a 64-bit value. As shown on page 106 of RISCV-ISA-Specification, the instruction format is as follows:
00011 | aq<1> | rl<1> | rs2<5> | rs1<5> | 011 | rd<5> | 0101111
In order to use inline assembly to generate the corresponding code for SC.W instruction, we need 3 registers. The register list can be found here.
The register field of the instruction is 5 bit each. Hence, there are 32 general registers in RISC-V: x0, x1, ... x31. Each register has its own ABI(application binary interface), for instance, register x16 corresponds to a6 register, hence, the corresponding 5-bit value should be 10000.
I choose the following registers assignment:
rs2: a6 register (register x16, i.e. 0b10000)
rs1: a7 register (register x17, i.e. 0b10001)
rd: s4 register (register x20, i.e. 0b10100)
Hence, by filling in the corresponding register bits of the original instruction, we have the following:
00011 | aq<1> | rl<1> | 10000 | 10001 | 011 | 10100 | 0101111
For the two bits aq and rl, it is used for specifying the ordering constraints (page 40 of RISCV-ISA-Specification):
If both the aq and rl bits are set, the atomic
memory operation is sequentially consistent and cannot be observed to happen before any earlier
memory operations or after any later memory operations in the same RISC-V hart, and can only be
observed by any other hart in the same global order of all sequentially consistent atomic memory
operations to the same address domain.
So we just set both bits to 1 since we want SC.D to be executed atomically. Now we have the final instruction bits:
00011 | 1 | 1 | 10000 | 10001 | 011 | 10100 | 0101111
-> 00011111|00001000|10111010|00101111
0x1f 0x08 0xba 0x2f
Since RISC-V uses little endian, the corresponding inline assembly can be generated by:
__asm__ volatile(".byte 0x2f, 0xba, 0x08, 0x1f");
There are also some other preparations like loading values into rs1(a7) and rs2(a6) registers. Therefore, I have the following code (but it did not work as expected):
/**
* rs2: holds the value to be written. I pick a6 register.
* rs1: holds the address to be written to. I pick a7 register.
* rd: holds the return value of SC.D instruction. I pick s4 register.
*
* #src: the value to be written. rs2. a6 register
* #dst: the address to be written to. rs1. a7 register
* #rd: the value that holds the return value of SC.D
*/
static inline void sc(void *src, void *dst, uint64_t *rd) {
uint64_t *tmp_src = (uint64_t *)src;
uint64_t src_val = *tmp_src; // 13
uint64_t dst_addr = (uint64_t)dst;
uint64_t ret = 100;
// first of all, need to prepare the registers a6 and a7.
/* load value to be written into register a6 */
__asm__ volatile("ld a6, %0"::"m"(src_val));
/* load the address to be written to into register a7 */
__asm__ volatile("ld a7, %0"::"m"(dst_addr));
/* the actual SC.D: */
__asm__ volatile(".byte 0x2f, 0xba, 0x08, 0x1f");
// __asm__ volatile("sc.d s4, a6, (a7)"); // this does not work either.
/* obtain the value in register s4 */
__asm__ volatile("sd s4, %0":"=m"(ret));
*rd = ret;
return;
}
int main() {
uint64_t *src = malloc(sizeof(uint64_t));
uint64_t *dst = malloc(sizeof(uint64_t));
uint64_t rd = 20;
*src = 13;
*dst = 3;
sc(src, dst, &rd); // write value 13 into #dst, so #dst should be 13 afterwards
// the expected output should be "dst: 13, rd: 0"
// What I get: "dst: 3, rd: 1"
printf("dst: %ld, rd: %ld\n", *src, *dst, rd);
return 0;
}
The result does not seem to change the dst value. May I know which part I am doing wrong? Any hints would be appreciated.
I try to create a code that would read data from RFID reader module. In order to do this I need to do CRC16 CCITT calculation.
I have found C source code for the CRC16 checksum calculation in the reader manufacturer application technical datasheet http://www.card-sys.com/manuals/framer_eng.pdf
Unfortunately this is just a part of code not a full working example.
When the RFID reader is put in automatic mode, it automatically sends 11 bytes every time it reads a tag. CRC - this value is calculated using all of the bytes except the last two bytes which are the CRCH (CRC high byte) and CRCL (CRC low byte).
When I read RFID tag from a reader I got 11 bytes transferred... i.e. (hex) 01 0B 03 01 06 87 DB C7 FF E5 68. Last two bytes E5 68 are the CRC16 checksum for the message. In order to confirm the data is OK I need to calculate the same CRC16 against 01 0B 03 01 06 87 DB C7 FF at the destination point.
I tried putting everything together in one piece, but I do not have much experience with C programing and my code does not work.
Here is the source code:
#include <stdio.h>
#include <stdlib.h>
// CRC16 from Netronix datasheet
void CRC16(unsigned char * Data, unsigned short * CRC, unsigned char Bytes)
{
int i, byte;
unsigned short C;
*CRC = 0;
for (byte = 1; byte <= Bytes; byte ++, Data ++)
{
C = ((*CRC >> 8) ^ *Data) << 8;
for (i = 0; i < 8; i ++)
{
if (C & 0x8000)
C = (C << 1) ^ 0x1021;
else
C = C << 1;
}
*CRC = C ^ (*CRC << 8);
}
}
int main(void)
{
puts("Test...");
unsigned char * Data16="10ac0501ff";
unsigned short * CRC=0;
unsigned char Bytes16=4;
CRC16(Data16,CRC,Bytes16);
puts(CRC);
return EXIT_SUCCESS;
}
What I would like to do is learn how to use manufacturer code in working example - means how to get crc16 calculated.
Could you please help me with this? Thanks.
Using your source code I created the following program.
#include <stdio.h>
#include <stdlib.h>
// CRC16 from Netronix datasheet
void CRC16(unsigned char * Data, unsigned short * CRC, unsigned char Bytes)
{
int i, byte;
unsigned short C;
*CRC = 0;
for (byte = 1; byte <= Bytes; byte++, Data++)
{
C = ((*CRC >> 8) ^ *Data) << 8;
for (i = 0; i < 8; i++)
{
if (C & 0x8000)
C = (C << 1) ^ 0x1021;
else
C = C << 1;
}
*CRC = C ^ (*CRC << 8);
}
}
int main(void)
{
// When I read RFID tag from a reader I got 11 bytes transferred... i.e.
// (hex)01 0B 03 01 06 87 DB C7 FF E5 68.
// Last two bytes E5 68 are crc16.
// In order to confirm the data is OK I need to calculate the same crc16
// against 01 0B 03 01 06 87 DB C7 FF at the destination point.
unsigned char Data16[] = { 0x01, 0x0B, 0x03, 0x01, 0x06, 0x87, 0xDB, 0xC7, 0xFF };
unsigned short CRC = 0;
unsigned char Bytes16 = 9;
CRC16(Data16, &CRC, Bytes16);
printf(" CRC calculated is %x\n", CRC);
return EXIT_SUCCESS;
}
The output is CRC calculated is e568.
There are a couple of changes I made.
First is the data I used which is from your comment on the RFID tag reader output.
When I read RFID tag from a reader I got 11 bytes transferred... i.e.
(hex) 01 0B 03 01 06 87 DB C7 FF E5 68. Last two bytes E5 68 are
crc16. In order to confirm the data is OK I need to calculate the same
crc16 against 01 0B 03 01 06 87 DB C7 FF at the destination point. You
are probably right about the Data16[]... I will change this later
today and let you know what current status is. Thanks for helping :)
I used a length of the data that excludes the checksum. So the length in the frame data is 0x0B or 11 and since the checksum is 2 bytes, I used 11 - 2 or 9 for the length.
Finally I changed the definition of the variable CRC to unsigned short CRC = 0; and when calling the CRC function, I used the address of operator as in CRC16(Data16, &CRC, Bytes16);.
Frame format for serial transmission
From the documentation you referenced there are two types of frames or messages whose formats are as follows:
Command frame:
module address (1 byte) unique address of each module in network
frame length (1 byte) full length of frame (includes 2 byte checksum)
command (1 byte) command code which is an even value
parameters (variable length) optional parameters depending on command
CRCH (1 byte) upper byte of the CRC16
CRCL (1 byte) lower byte of the CRC16
Answer frame:
module address (1 byte) unique address of each module in network
frame length (1 byte) full length of frame (includes 2 byte checksum)
answer(1 byte) answer code which is an odd value
parameters (variable length) optional parameters depending on command
operation code (1 byte) command execution status
CRCH (1 byte) upper byte of the CRC16
CRCL (1 byte) lower byte of the CRC16
Given the following assembly code for a 16-bit PRNG function,
$80/8111 E2 20 SEP #$20 ; set 8-bit mode accumulator
$80/8113 AD E5 05 LDA $05E5 ; load low byte of last random number
$80/8116 8D 02 42 STA $4202
$80/8119 A9 05 LDA #$05 ; multiply it by 5
$80/811B 8D 03 42 STA $4203
$80/811E EA NOP
$80/811F C2 20 REP #$20 ; set 16-bit mode accumulator
$80/8121 AD 16 42 LDA $4216 ; load the resultant product
$80/8124 48 PHA ; push it onto the stack
$80/8125 E2 20 SEP #$20 ; 8-bit
$80/8127 AD E6 05 LDA $05E6 ; load high byte of last random number
$80/812A 8D 02 42 STA $4202
$80/812D A9 05 LDA #$05 ; multiply by 5
$80/812F 8D 03 42 STA $4203
$80/8132 EB XBA ; exchange high and low bytes of accumulator
$80/8133 EA NOP
$80/8134 AD 16 42 LDA $4216 ; load low byte of product
$80/8137 38 SEC
$80/8138 63 02 ADC $02,s ; add to it the high byte of the original product
$80/813A 83 02 STA $02,s ; save it to the high byte of the original product
$80/813C C2 20 REP #$20 ; 16-bit
$80/813E 68 PLA ; pull it from the stack
$80/813F 69 11 00 ADC #$0011 ; add 11
$80/8142 8D E5 05 STA $05E5 ; save as new random number
$80/8145 6B RTL
a user by the name of #sagara translated the code to C:
#define LOW(exp) ((exp) & 0x00FF)
#define HIGH(exp) (((exp) & 0xFF00) >> 8)
uint16_t prng(uint16_t v) {
uint16_t low = LOW(v);
uint16_t high = HIGH(v);
uint16_t mul_low = low * 5;
uint16_t mul_high = high * 5;
// need to check for overflow, since final addition is adc as well
uint16_t v1 = LOW(mul_high) + HIGH(mul_low) + 1;
uint8_t carry = HIGH(v1) ? 1 : 0;
uint16_t v2 = (LOW(v1) << 8) + LOW(mul_low);
return (v2 + 0x11 + carry);
}
I'm confused by two things.
In this line...
uint16_t v1 = LOW(mul_high) + HIGH(mul_low) + 1;
Why is there a + 1? I think it's because of the ADC operation, but how can we be sure that the carry flag is set to 1? What previous operation would guarantee this? The XBC? I read a few posts such as Assembly ADC (Add with carry) to C++ and Overflow and Carry flags on Z80 but it's not clear to me because the instruction set appears to be different I'm not familiar with 65C816 assembly. (This is from a popular 1994 SNES game whose NA release anniversary recently passed; free upvote to the correct guess :-)
In the next line...
uint8_t carry = HIGH(v1) ? 1 : 0;
Why would it work this way? I read this as, "Set the carry flag if and only if the high byte is non-zero." But wouldn't the indication of an overflow be only if the high byte is zero? (I'm probably misinterpreting what the line is doing.)
Thanks in advance for any insights.
but how can we be sure that the carry flag is set to 1? What previous operation would guarantee this?
$80/8137 38 SEC ; SEt Carry flag
uint8_t carry = HIGH(v1) ? 1 : 0;
Why would it work this way? I read this as, "Set the carry flag if and only if the high byte is non-zero." But wouldn't the indication of an overflow be only if the high byte is zero?
The addition ADC #$0011 is using the carry from ADC $02,s. When ADC $02,s is performed, the accumulator is set to 8-bit (because of SEP #$20), so the carry flag will be set if the result of ADC $02,s would've exceeded 8 bits (i.e. if you would've got something >= $100 in 16-bit mode).
In the C version you've got a 16-bit variable (v1) to hold the result, so your carry will be in bit 8 of v1, which you can test with HIGH(v1) == 1, or simply HIGH(v1) since it will either be 1 or 0.
1) The line
$80/8137 38 SEC
is explicity setting the carry just before an ADC add-with-carry instruction, that's why the +1 in the C code.
2) The processor has an 8-bit accumulator, and the addition will overflow to the carry, ready for the next ADC instruction. However, the C code is using a 16-bit variable v1, and the carry remains in the upper 8 bits. Hence the test of those upper 8 bits to extract the so-called "carry".
I'm writing code to configure the serial port on a pic32 family device. The initialization appears to work for the most part, but I get garbage data in place of the first 6 characters that I write. I noticed, however, that if I add an arbitrarily long wait at the end of the initialization function, this goes away. Is there some register flag that I need to be waiting on at the end of my initialization? My initialization code is below. If it helps, I am basing this initialization off of the UART section in the pic32 reference manual. I added the code below for my transmission function as well. My expected output string is "Hello from the bootloader code.\r\n" but the actual bytes I get are:
00000000 00 00 aa b1 b1 bd 81 66 72 6f 6d 20 74 68 65 20 |.......from the |
00000010 62 6f 6f 74 6c 6f 61 64 65 72 20 63 6f 64 65 2e |bootloader code.|
00000020 0d 0a
void initializeUART2()
{
uint32 counter;
initialized = TRUE;
U2MODE = 0;
U2STA = 0;
U2BRG = 0;
IEC1bits.U2TXIE = 0;
IEC1bits.U2RXIE = 0;
IEC1bits.U2EIE = 0;
//disable UART transmission before config
U2STA &= ~UART_TRANSMIT_ENABLED_STATUS_FLAG;
//disable UART before config
U2MODE &= ~UART_ENABLED_MODE_FLAG;
RS232_RS485_TRIS=0; //set to output
RS232_RS485=0; //select RS-232 mode on MAX3161
//set baudrate BAUDRATE = CLOCK_FREQUENCY/(16*(U2BRG + 1))
//solve for U2BRG value
U2BRG = (UINT16)(((PERIPHERAL_CLOCK_FREQUENCY/UART2_BAUDRATE)/16)-1);
//set mode to 8 bit no parity
U2MODE &= ~UART_PARITY_DATA_MODE_BITS;
//set number of stop bits to 1
U2MODE &= ~UART_EXTRA_STOP_MODE_BIT_FLAG;
//enable the UART port
U2MODE |= UART_ENABLED_MODE_FLAG;
//enable serial transmission
U2STA |= UART_TRANSMIT_ENABLED_STATUS_FLAG;
//without this loop, I get garbage in first 6 bytes of my first message
counter = 1000;
while(counter--);
}
void putUART2(uint32 value)
{
if(!initialized)
{
initializeUART2();
}
//make sure value is in range of writable values
value &= UINT32_MASK(8);
//clear transmit interrupt flag
IFS1bits.U2TXIF = 0;
//wait for the transmit buffer to be empty
while((U2STA & UART_TRANSMIT_STATUS_FLAG) == 0);
//set the data byte to be written in the write register
//also starts transmission
U2TXREG = value;
//wait for the transmit buffer to be empty
//both of these waits are necessary to avoid missing bytes
while((U2STA & UART_TRANSMIT_STATUS_FLAG) == 0);
}
The MAX3161 needs at least 100 ns to stabilize after switching modes to RS232.
Also, these lines:
RS232_RS485_TRIS=0; //set to output
RS232_RS485=0; //select RS-232 mode on MAX3161
should be reversed; set the output, then the direction register to avoid glitches.
Suspect the MAX3161 chip, which has charge pumps, needs the additional time to reach stable operating voltages.
It may be only for a bit time or 2, but if a message is sent too early, the serial output is messed until a quiet time occurs.
Lesser candidate: problem is an interaction between this and the unposted send routine.
Note: It's amazing how seeing using info like the unposted "garbage data" may help. Also knowing what the "good" first 6 bytes or so is useful.
[Edit] #Doug Currie is on the right track.
When RS232_RS485_TRIS1 is changed to output, a delay time as he suggest is needed before data is sent. This applies here as well as other place in code.
Further, before RS232_RS485_TRIS1 is changed to input, code needs to insure all the data is completely transmitted. This may be a 10/baud after the the PIC declares the xmit buffer empty. Or check the proper xmit status bit before turning the bus around. (Shift Register empty - names vary depending on compiler.)
Suppose that an instruction aw is code 010 defined by a 32 bit structure as follows:
bits 31-25 unused (all 0s)
bits 24-22: code
bits 21-19: argument 1
bits 18-16: argument 2
bits 15-0: offset (a 16-bit, 2's complement number with a range of -32768 to 32767)
Given the number 8454151, how can I determine if the code is aw?
I tried to shift the number 22 bits, like 8454151 >> 22, but I keep getting 0. Any ideas on how I can obtain the bit information for the code (to check whether it's aw or something else)?
If you just have to verify if an instruction is of a certain operation, the code needing the least cycles would be as follows:
const uint32_t mask = 7 << 22; // Shift 3 set bits by 22 in order to build
// a mask where bits 22-24 are set.
const uint32_t inst_aw = 2 << 22; // Shift the opcode by 22 to build a comparable value
uint32_t instruction = ...; // Your instruction word
if ((instruction & mask) == inst_aw) {
// Do your thing
}
Anyway if you have to build something like an "instruction decoder" or "interpreter", I'd recommend using a lookup table with instruction names (or function pointers) indexed by the instruction code:
/*! \brief Instruction names lookup table. Make sure it has always 8 entries
in order to avoid access beyond the array limits */
const char *instruction_names[] = {
/* 000 */ "Unknown instruction 000",
/* 001 */ "Unknown instruction 001",
/* 010 */ "AW",
...
/* 111 */ "Unknown instruction 111"
};
uint32_t instruction = ...;
unsigned int opcode = (instruction >> 22) & 0x07; // Retrieving the opcode by shifting right 22
// times and mask out all bit except the last 3
printf("Instruction is: %s", instruction_names[opcode]);
A bit shift should work. Be sure to check the data types. You can also "and" the number with 0x01C000 and then compare.