сделан idle
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
/STM32F103_Example/MDK-ARM/Modbus_example
|
/STM32F103_Example/MDK-ARM/Modbus_example
|
||||||
|
/Modbus/.vs/
|
||||||
|
|||||||
116
Modbus/__crc_algs.c
Normal file
116
Modbus/__crc_algs.c
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
#include "__crc_algs.h"
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t CRC_calc;
|
||||||
|
uint32_t CRC_ref;
|
||||||
|
|
||||||
|
//uint16_t CRC_calc;
|
||||||
|
//uint16_t CRC_ref;
|
||||||
|
|
||||||
|
|
||||||
|
// left this global for debug
|
||||||
|
uint8_t uchCRCHi = 0xFF;
|
||||||
|
uint8_t uchCRCLo = 0xFF;
|
||||||
|
unsigned uIndex;
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t crc32(uint8_t *data, uint32_t data_size)
|
||||||
|
{
|
||||||
|
static const unsigned int crc32_table[] =
|
||||||
|
{
|
||||||
|
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||||
|
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
||||||
|
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
||||||
|
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
|
||||||
|
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
||||||
|
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
||||||
|
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
|
||||||
|
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
|
||||||
|
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
||||||
|
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
|
||||||
|
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
|
||||||
|
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
||||||
|
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
|
||||||
|
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
|
||||||
|
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
||||||
|
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
|
||||||
|
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
|
||||||
|
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
||||||
|
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
|
||||||
|
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
|
||||||
|
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
||||||
|
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
|
||||||
|
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
|
||||||
|
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
||||||
|
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
|
||||||
|
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
|
||||||
|
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
||||||
|
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
|
||||||
|
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
|
||||||
|
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
||||||
|
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
||||||
|
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
|
||||||
|
};
|
||||||
|
unsigned int crc = 0xFFFFFFFF;
|
||||||
|
while (data_size--)
|
||||||
|
{
|
||||||
|
crc = (crc >> 8) ^ crc32_table[(crc ^ *data) & 255];
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
return crc^0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t crc16(uint8_t *data, uint32_t data_size)
|
||||||
|
{
|
||||||
|
/*Table of CRC values for high order byte*/
|
||||||
|
static unsigned char auchCRCHi[]=
|
||||||
|
{
|
||||||
|
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||||
|
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||||
|
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||||
|
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||||
|
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||||
|
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||||
|
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||||
|
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||||
|
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||||
|
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||||
|
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||||
|
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||||
|
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||||
|
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||||
|
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||||
|
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||||
|
};
|
||||||
|
/*Table of CRC values for low order byte*/
|
||||||
|
static char auchCRCLo[] =
|
||||||
|
{
|
||||||
|
0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4,0x04,
|
||||||
|
0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09,0x08,0xC8,
|
||||||
|
0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC,
|
||||||
|
0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,0x11,0xD1,0xD0,0x10,
|
||||||
|
0xF0,0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,0x36,0xF6,0xF7,0x37,0xF5,0x35,0x34,0xF4,
|
||||||
|
0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,0x3B,0xFB,0x39,0xF9,0xF8,0x38,
|
||||||
|
0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA,0xEE,0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,
|
||||||
|
0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,
|
||||||
|
0xA0,0x60,0x61,0xA1,0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4,
|
||||||
|
0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68,
|
||||||
|
0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,
|
||||||
|
0xB4,0x74,0x75,0xB5,0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,
|
||||||
|
0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,
|
||||||
|
0x9C,0x5C,0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98,
|
||||||
|
0x88,0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,
|
||||||
|
0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40,
|
||||||
|
};
|
||||||
|
uchCRCHi = 0xFF;
|
||||||
|
uchCRCLo = 0xFF;
|
||||||
|
/* CRC Generation Function */
|
||||||
|
while( data_size--) /* pass through message buffer */
|
||||||
|
{
|
||||||
|
uIndex = uchCRCHi ^ *data++; /* calculate the CRC */
|
||||||
|
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
|
||||||
|
uchCRCLo = auchCRCLo[uIndex];
|
||||||
|
}
|
||||||
|
return uchCRCHi | uchCRCLo<<8;
|
||||||
|
}
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
#include "crc_algs.h"
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t CRC_calc;
|
|
||||||
uint32_t CRC_ref;
|
|
||||||
|
|
||||||
//uint16_t CRC_calc;
|
|
||||||
//uint16_t CRC_ref;
|
|
||||||
|
|
||||||
|
|
||||||
// left this global for debug
|
|
||||||
uint8_t uchCRCHi = 0xFF;
|
|
||||||
uint8_t uchCRCLo = 0xFF;
|
|
||||||
unsigned uIndex;
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t crc32(uint8_t *data, uint32_t data_size)
|
|
||||||
{
|
|
||||||
static const unsigned int crc32_table[] =
|
|
||||||
{
|
|
||||||
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
|
||||||
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
|
||||||
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
|
||||||
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
|
|
||||||
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
|
||||||
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
|
||||||
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
|
|
||||||
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
|
|
||||||
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
|
||||||
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
|
|
||||||
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
|
|
||||||
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
|
||||||
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
|
|
||||||
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
|
|
||||||
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
|
||||||
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
|
|
||||||
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
|
|
||||||
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
|
||||||
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
|
|
||||||
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
|
|
||||||
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
|
||||||
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
|
|
||||||
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
|
|
||||||
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
|
||||||
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
|
|
||||||
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
|
|
||||||
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
|
||||||
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
|
|
||||||
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
|
|
||||||
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
|
||||||
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
|
||||||
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
|
|
||||||
};
|
|
||||||
unsigned int crc = 0xFFFFFFFF;
|
|
||||||
while (data_size--)
|
|
||||||
{
|
|
||||||
crc = (crc >> 8) ^ crc32_table[(crc ^ *data) & 255];
|
|
||||||
data++;
|
|
||||||
}
|
|
||||||
return crc^0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint16_t crc16(uint8_t *data, uint32_t data_size)
|
|
||||||
{
|
|
||||||
/*Table of CRC values for high order byte*/
|
|
||||||
static unsigned char auchCRCHi[]=
|
|
||||||
{
|
|
||||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
|
||||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
|
||||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
|
||||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
|
||||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
|
||||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
|
||||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
|
||||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
|
||||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
|
||||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
|
||||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
|
||||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
|
||||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
|
||||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
|
||||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
|
||||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
|
||||||
};
|
|
||||||
/*Table of CRC values for low order byte*/
|
|
||||||
static char auchCRCLo[] =
|
|
||||||
{
|
|
||||||
0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4,0x04,
|
|
||||||
0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09,0x08,0xC8,
|
|
||||||
0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC,
|
|
||||||
0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,0x11,0xD1,0xD0,0x10,
|
|
||||||
0xF0,0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,0x36,0xF6,0xF7,0x37,0xF5,0x35,0x34,0xF4,
|
|
||||||
0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,0x3B,0xFB,0x39,0xF9,0xF8,0x38,
|
|
||||||
0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA,0xEE,0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,
|
|
||||||
0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,
|
|
||||||
0xA0,0x60,0x61,0xA1,0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4,
|
|
||||||
0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68,
|
|
||||||
0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,
|
|
||||||
0xB4,0x74,0x75,0xB5,0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,
|
|
||||||
0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,
|
|
||||||
0x9C,0x5C,0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98,
|
|
||||||
0x88,0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,
|
|
||||||
0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40,
|
|
||||||
};
|
|
||||||
uchCRCHi = 0xFF;
|
|
||||||
uchCRCLo = 0xFF;
|
|
||||||
/* CRC Generation Function */
|
|
||||||
while( data_size--) /* pass through message buffer */
|
|
||||||
{
|
|
||||||
uIndex = uchCRCHi ^ *data++; /* calculate the CRC */
|
|
||||||
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
|
|
||||||
uchCRCLo = auchCRCLo[uIndex];
|
|
||||||
}
|
|
||||||
return uchCRCHi | uchCRCLo<<8;
|
|
||||||
}
|
|
||||||
242
Modbus/modbus.c
242
Modbus/modbus.c
@@ -24,11 +24,12 @@
|
|||||||
* - MB_DefineCoilsAddress() — Определить начальный адрес coils.
|
* - MB_DefineCoilsAddress() — Определить начальный адрес coils.
|
||||||
* - MB_Check_Address_For_Arr() — Проверить, принадлежит ли адрес массиву.
|
* - MB_Check_Address_For_Arr() — Проверить, принадлежит ли адрес массиву.
|
||||||
* - Основные команды Modbus:
|
* - Основные команды Modbus:
|
||||||
* - MB_Read_Coils()
|
* - MB_Proccess_Read_Coils()
|
||||||
* - MB_Read_Hold_Regs()
|
* - MB_Proccess_Read_Hold_Regs()
|
||||||
* - MB_Write_Single_Coil()
|
* - MB_Proccess_Write_Single_Coil()
|
||||||
|
* - MB_Proccess_Write_Single_Reg()
|
||||||
* - MB_Write_Miltuple_Coils()
|
* - MB_Write_Miltuple_Coils()
|
||||||
* - MB_Write_Miltuple_Regs()
|
* - MB_Proccess_Write_Miltuple_Regs()
|
||||||
*
|
*
|
||||||
* ### Функции для работы с RS (UART):
|
* ### Функции для работы с RS (UART):
|
||||||
* - RS_Parse_Message() / RS_Collect_Message() — Парсинг и сборка сообщения.
|
* - RS_Parse_Message() / RS_Collect_Message() — Парсинг и сборка сообщения.
|
||||||
@@ -72,8 +73,8 @@ extern TIM_HandleTypeDef rs_htim;
|
|||||||
RS_HandleTypeDef hmodbus1;
|
RS_HandleTypeDef hmodbus1;
|
||||||
|
|
||||||
/* DEFINE REGISTERS/COILS */
|
/* DEFINE REGISTERS/COILS */
|
||||||
MB_DeviceIdentificationTypeDef MB_INFO;
|
MB_DeviceIdentificationTypeDef MB_DEVID;
|
||||||
MB_DataStructureTypeDef MB_DATA;
|
MB_DataStructureTypeDef MB_DATA = {0};;
|
||||||
RS_MsgTypeDef MODBUS_MSG;
|
RS_MsgTypeDef MODBUS_MSG;
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
@@ -85,7 +86,7 @@ RS_MsgTypeDef MODBUS_MSG;
|
|||||||
*/
|
*/
|
||||||
void MODBUS_FirstInit(void)
|
void MODBUS_FirstInit(void)
|
||||||
{
|
{
|
||||||
MB_DevoceInentificationInit();
|
MB_DeviceInentificationInit();
|
||||||
//-----------SETUP MODBUS-------------
|
//-----------SETUP MODBUS-------------
|
||||||
// set up modbus: MB_RX_Size_NotConst and Timeout enable
|
// set up modbus: MB_RX_Size_NotConst and Timeout enable
|
||||||
hmodbus1.ID = MODBUS_DEVICE_ID;
|
hmodbus1.ID = MODBUS_DEVICE_ID;
|
||||||
@@ -295,7 +296,7 @@ MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint
|
|||||||
* @return fMessageHandled - статус о результате обработки комманды.
|
* @return fMessageHandled - статус о результате обработки комманды.
|
||||||
* @details Обработка команды Read Coils.
|
* @details Обработка команды Read Coils.
|
||||||
*/
|
*/
|
||||||
uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg)
|
uint8_t MB_Proccess_Read_Coils(RS_MsgTypeDef *modbus_msg)
|
||||||
{
|
{
|
||||||
//---------CHECK FOR ERRORS----------
|
//---------CHECK FOR ERRORS----------
|
||||||
uint16_t *coils;
|
uint16_t *coils;
|
||||||
@@ -348,7 +349,7 @@ uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg)
|
|||||||
* @return fMessageHandled - статус о результате обработки комманды.
|
* @return fMessageHandled - статус о результате обработки комманды.
|
||||||
* @details Обработка команды Read Holding Registers.
|
* @details Обработка команды Read Holding Registers.
|
||||||
*/
|
*/
|
||||||
uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg)
|
uint8_t MB_Proccess_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg)
|
||||||
{
|
{
|
||||||
//---------CHECK FOR ERRORS----------
|
//---------CHECK FOR ERRORS----------
|
||||||
// get origin address for data
|
// get origin address for data
|
||||||
@@ -376,7 +377,7 @@ uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg)
|
|||||||
* @return fMessageHandled - статус о результате обработки комманды.
|
* @return fMessageHandled - статус о результате обработки комманды.
|
||||||
* @details Обработка команды Read Input Registers.
|
* @details Обработка команды Read Input Registers.
|
||||||
*/
|
*/
|
||||||
uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg)
|
uint8_t MB_Proccess_Read_Input_Regs(RS_MsgTypeDef *modbus_msg)
|
||||||
{
|
{
|
||||||
//---------CHECK FOR ERRORS----------
|
//---------CHECK FOR ERRORS----------
|
||||||
// get origin address for data
|
// get origin address for data
|
||||||
@@ -406,7 +407,7 @@ uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg)
|
|||||||
* @return fMessageHandled - статус о результате обработки комманды.
|
* @return fMessageHandled - статус о результате обработки комманды.
|
||||||
* @details Обработка команды Write Single Coils.
|
* @details Обработка команды Write Single Coils.
|
||||||
*/
|
*/
|
||||||
uint8_t MB_Write_Single_Coil(RS_MsgTypeDef *modbus_msg)
|
uint8_t MB_Proccess_Write_Single_Coil(RS_MsgTypeDef *modbus_msg)
|
||||||
{
|
{
|
||||||
//---------CHECK FOR ERRORS----------
|
//---------CHECK FOR ERRORS----------
|
||||||
if ((modbus_msg->Qnt != 0x0000) && (modbus_msg->Qnt != 0xFF00))
|
if ((modbus_msg->Qnt != 0x0000) && (modbus_msg->Qnt != 0xFF00))
|
||||||
@@ -437,7 +438,7 @@ uint8_t MB_Write_Single_Coil(RS_MsgTypeDef *modbus_msg)
|
|||||||
* @return fMessageHandled - статус о результате обработки комманды.
|
* @return fMessageHandled - статус о результате обработки комманды.
|
||||||
* @details Обработка команды Write Single Register.
|
* @details Обработка команды Write Single Register.
|
||||||
*/
|
*/
|
||||||
uint8_t MB_Write_Single_Reg(RS_MsgTypeDef *modbus_msg)
|
uint8_t MB_Proccess_Write_Single_Reg(RS_MsgTypeDef *modbus_msg)
|
||||||
{
|
{
|
||||||
// get origin address for data
|
// get origin address for data
|
||||||
uint16_t *pHoldRegs;
|
uint16_t *pHoldRegs;
|
||||||
@@ -523,7 +524,7 @@ uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg)
|
|||||||
* @return fMessageHandled - статус о результате обработки комманды.
|
* @return fMessageHandled - статус о результате обработки комманды.
|
||||||
* @details Обработка команды Write Multiple Registers.
|
* @details Обработка команды Write Multiple Registers.
|
||||||
*/
|
*/
|
||||||
uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg)
|
uint8_t MB_Proccess_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg)
|
||||||
{
|
{
|
||||||
//---------CHECK FOR ERRORS----------
|
//---------CHECK FOR ERRORS----------
|
||||||
if (modbus_msg->Qnt*2 != modbus_msg->ByteCnt)
|
if (modbus_msg->Qnt*2 != modbus_msg->ByteCnt)
|
||||||
@@ -545,7 +546,13 @@ uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MB_WriteObjectToMessage(char *mbdata, unsigned *ind, MB_DeviceObjectTypeDef *obj)
|
|
||||||
|
/**
|
||||||
|
* @brief Write Object of Device Identification to MessageData
|
||||||
|
* @param mbdata - указатель на массив данных в структуре RS_MsgTypeDef.
|
||||||
|
* @return obj - объект для записи.
|
||||||
|
*/
|
||||||
|
void MB_WriteSingleObjectToMessage(char *mbdata, unsigned *ind, MB_DeviceObjectTypeDef *obj)
|
||||||
{
|
{
|
||||||
mbdata[(*ind)++] = obj->length;
|
mbdata[(*ind)++] = obj->length;
|
||||||
for (int i = 0; i < obj->length; i++)
|
for (int i = 0; i < obj->length; i++)
|
||||||
@@ -553,43 +560,106 @@ void MB_WriteObjectToMessage(char *mbdata, unsigned *ind, MB_DeviceObjectTypeDef
|
|||||||
mbdata[(*ind)++] = obj->name[i];
|
mbdata[(*ind)++] = obj->name[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write Object of Device Identification to MessageData
|
||||||
|
* @param mbdata - указатель на массив данных в структуре RS_MsgTypeDef.
|
||||||
|
* @return obj - объект для записи.
|
||||||
|
*/
|
||||||
|
void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj)
|
||||||
|
{
|
||||||
|
MB_DeviceObjectTypeDef *obj = (MB_DeviceObjectTypeDef *)&MB_DEVID;
|
||||||
|
unsigned objidtmp = modbus_msg->DevId.NextObjId;
|
||||||
|
|
||||||
|
/* Define number of object in one message */
|
||||||
|
unsigned lastobjid = 0;
|
||||||
|
for(int i = 0; i < DATA_SIZE*2;)
|
||||||
|
{
|
||||||
|
i += 2;
|
||||||
|
i += obj[objidtmp].length;
|
||||||
|
/* Если все еще помещается в массив переходим на следующий объект */
|
||||||
|
if(i < DATA_SIZE*2)
|
||||||
|
{
|
||||||
|
objidtmp++;
|
||||||
|
}
|
||||||
|
/* Если объекты для записи закончились - выходим из цикла*/
|
||||||
|
if(objidtmp > maxidofobj)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastobjid = objidtmp-1;
|
||||||
|
|
||||||
|
|
||||||
|
/* Fill message with objects data */
|
||||||
|
char *mbdata = (char *)&modbus_msg->DATA;
|
||||||
|
unsigned ind = 0;
|
||||||
|
unsigned objid = modbus_msg->DevId.NextObjId;
|
||||||
|
for(; objid <= lastobjid; objid++)
|
||||||
|
{
|
||||||
|
mbdata[ind++] = objid;
|
||||||
|
MB_WriteSingleObjectToMessage(mbdata, &ind, &obj[objid]);
|
||||||
|
}
|
||||||
|
objid--;
|
||||||
|
modbus_msg->ByteCnt = ind;
|
||||||
|
modbus_msg->DevId.NextObjId = lastobjid+1;
|
||||||
|
if(objid == maxidofobj)
|
||||||
|
{
|
||||||
|
modbus_msg->DevId.MoreFollows = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
modbus_msg->DevId.MoreFollows = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Proccess command Read Device Identification (43/14 - 0x2B/0E).
|
* @brief Proccess command Read Device Identification (43/14 - 0x2B/0E).
|
||||||
* @param modbus_msg - указатель на структуру собщения modbus.
|
* @param modbus_msg - указатель на структуру собщения modbus.
|
||||||
* @return fMessageHandled - статус о результате обработки комманды.
|
* @return fMessageHandled - статус о результате обработки комманды.
|
||||||
* @details Обработка команды Write Single Register.
|
* @details Обработка команды Write Single Register.
|
||||||
*/
|
*/
|
||||||
uint8_t MB_Read_Device_Identification(RS_MsgTypeDef *modbus_msg)
|
uint8_t MB_Proccess_Read_Device_Identification(RS_MsgTypeDef *modbus_msg)
|
||||||
{
|
{
|
||||||
char *mbdata = (char *)modbus_msg->DATA;
|
|
||||||
unsigned ind = 0;
|
|
||||||
switch(modbus_msg->DevId.ReadDevId)
|
switch(modbus_msg->DevId.ReadDevId)
|
||||||
{
|
{
|
||||||
case MB_BASIC_IDENTIFICATION:
|
case MB_BASIC_IDENTIFICATION:
|
||||||
mbdata[ind++] = 0x00;
|
if (modbus_msg->DevId.NextObjId == 0)
|
||||||
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.VendorName);
|
{
|
||||||
mbdata[ind++] = 0x01;
|
modbus_msg->DevId.NextObjId = 0;
|
||||||
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.ProductCode);
|
}
|
||||||
mbdata[ind++] = 0x02;
|
|
||||||
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.Revision);
|
MB_WriteObjectsToMessage(modbus_msg, 2);
|
||||||
modbus_msg->DevId.NumbOfObj = 3;
|
modbus_msg->DevId.NumbOfObj = 3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MB_REGULAR_IDENTIFICATION:
|
case MB_REGULAR_IDENTIFICATION:
|
||||||
mbdata[ind++] = 0x03;
|
if (modbus_msg->DevId.NextObjId == 0)
|
||||||
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.VendorUrl);
|
{
|
||||||
mbdata[ind++] = 0x04;
|
modbus_msg->DevId.NextObjId = 3;
|
||||||
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.ProductName);
|
}
|
||||||
mbdata[ind++] = 0x05;
|
|
||||||
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.ModelName);
|
MB_WriteObjectsToMessage(modbus_msg, 6);
|
||||||
mbdata[ind++] = 0x06;
|
|
||||||
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.UserApplicationName);
|
|
||||||
modbus_msg->DevId.NumbOfObj = 4;
|
modbus_msg->DevId.NumbOfObj = 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MB_EXTENDED_IDENTIFICATION:
|
||||||
|
if (modbus_msg->DevId.NextObjId == 0)
|
||||||
|
{
|
||||||
|
modbus_msg->DevId.NextObjId = 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
MB_WriteObjectsToMessage(modbus_msg, 0x80+MODBUS_NUMB_OF_USEROBJECTS);
|
||||||
|
modbus_msg->DevId.NumbOfObj = MODBUS_NUMB_OF_USEROBJECTS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MB_SPEDIFIC_IDENTIFICATION:
|
||||||
|
MB_WriteObjectsToMessage(modbus_msg, modbus_msg->DevId.NextObjId);
|
||||||
|
modbus_msg->DevId.NumbOfObj = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
modbus_msg->ByteCnt = ind;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -608,38 +678,46 @@ RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_ms
|
|||||||
hmodbus->f.EchoResponse = 0;
|
hmodbus->f.EchoResponse = 0;
|
||||||
RS_Reset_TX_Flags(hmodbus); // reset flag for correct transmit
|
RS_Reset_TX_Flags(hmodbus); // reset flag for correct transmit
|
||||||
|
|
||||||
|
if(hmodbus->ID == 0)
|
||||||
|
{
|
||||||
|
hmodbus->RS_STATUS = RS_SKIP;
|
||||||
|
return MB_RES;
|
||||||
|
}
|
||||||
|
|
||||||
if(modbus_msg->Func_Code < ERR_VALUES_START)// if no errors after parsing
|
if(modbus_msg->Func_Code < ERR_VALUES_START)// if no errors after parsing
|
||||||
{
|
{
|
||||||
switch (modbus_msg->Func_Code)
|
switch (modbus_msg->Func_Code)
|
||||||
{
|
{
|
||||||
// Read Coils
|
// Read Coils
|
||||||
case MB_R_COILS:
|
case MB_R_COILS:
|
||||||
hmodbus->f.MessageHandled = MB_Read_Coils(hmodbus->pMessagePtr);
|
hmodbus->f.MessageHandled = MB_Proccess_Read_Coils(hmodbus->pMessagePtr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Read Hodling Registers
|
// Read Hodling Registers
|
||||||
case MB_R_HOLD_REGS:
|
case MB_R_HOLD_REGS:
|
||||||
hmodbus->f.MessageHandled = MB_Read_Hold_Regs(hmodbus->pMessagePtr);
|
hmodbus->f.MessageHandled = MB_Proccess_Read_Hold_Regs(hmodbus->pMessagePtr);
|
||||||
break;
|
break;
|
||||||
case MB_R_IN_REGS:
|
case MB_R_IN_REGS:
|
||||||
hmodbus->f.MessageHandled = MB_Read_Input_Regs(hmodbus->pMessagePtr);
|
hmodbus->f.MessageHandled = MB_Proccess_Read_Input_Regs(hmodbus->pMessagePtr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
// Write Single Coils
|
// Write Single Coils
|
||||||
case MB_W_COIL:
|
case MB_W_COIL:
|
||||||
hmodbus->f.MessageHandled = MB_Write_Single_Coil(hmodbus->pMessagePtr);
|
hmodbus->f.MessageHandled = MB_Proccess_Write_Single_Coil(hmodbus->pMessagePtr);
|
||||||
if(hmodbus->f.MessageHandled)
|
if(hmodbus->f.MessageHandled)
|
||||||
{
|
{
|
||||||
|
hmodbus->f.DataUpdated = 1;
|
||||||
hmodbus->f.EchoResponse = 1;
|
hmodbus->f.EchoResponse = 1;
|
||||||
hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes)
|
hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MB_W_HOLD_REG:
|
case MB_W_HOLD_REG:
|
||||||
hmodbus->f.MessageHandled = MB_Write_Single_Reg(hmodbus->pMessagePtr);
|
hmodbus->f.MessageHandled = MB_Proccess_Write_Single_Reg(hmodbus->pMessagePtr);
|
||||||
if(hmodbus->f.MessageHandled)
|
if(hmodbus->f.MessageHandled)
|
||||||
{
|
{
|
||||||
|
hmodbus->f.DataUpdated = 1;
|
||||||
hmodbus->f.EchoResponse = 1;
|
hmodbus->f.EchoResponse = 1;
|
||||||
hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes)
|
hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes)
|
||||||
}
|
}
|
||||||
@@ -650,6 +728,7 @@ RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_ms
|
|||||||
hmodbus->f.MessageHandled = MB_Write_Miltuple_Coils(hmodbus->pMessagePtr);
|
hmodbus->f.MessageHandled = MB_Write_Miltuple_Coils(hmodbus->pMessagePtr);
|
||||||
if(hmodbus->f.MessageHandled)
|
if(hmodbus->f.MessageHandled)
|
||||||
{
|
{
|
||||||
|
hmodbus->f.DataUpdated = 1;
|
||||||
hmodbus->f.EchoResponse = 1;
|
hmodbus->f.EchoResponse = 1;
|
||||||
hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes)
|
hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes)
|
||||||
}
|
}
|
||||||
@@ -657,29 +736,31 @@ RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_ms
|
|||||||
|
|
||||||
// Write Multiple Registers
|
// Write Multiple Registers
|
||||||
case MB_W_HOLD_REGS:
|
case MB_W_HOLD_REGS:
|
||||||
hmodbus->f.MessageHandled = MB_Write_Miltuple_Regs(hmodbus->pMessagePtr);
|
hmodbus->f.MessageHandled = MB_Proccess_Write_Miltuple_Regs(hmodbus->pMessagePtr);
|
||||||
if(hmodbus->f.MessageHandled)
|
if(hmodbus->f.MessageHandled)
|
||||||
{
|
{
|
||||||
|
hmodbus->f.DataUpdated = 1;
|
||||||
hmodbus->f.EchoResponse = 1;
|
hmodbus->f.EchoResponse = 1;
|
||||||
hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes)
|
hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MB_R_DEVICE_INFO:
|
case MB_R_DEVICE_INFO:
|
||||||
hmodbus->f.MessageHandled = MB_Read_Device_Identification(hmodbus->pMessagePtr);
|
hmodbus->f.MessageHandled = MB_Proccess_Read_Device_Identification(hmodbus->pMessagePtr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
/* unknown func code */
|
/* unknown func code */
|
||||||
default: modbus_msg->Except_Code = 0x01; /* set exception code: illegal function */
|
default: modbus_msg->Except_Code = 0x01; /* set exception code: illegal function */
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hmodbus->f.MessageHandled == 0)
|
if(hmodbus->f.MessageHandled == 0)
|
||||||
{
|
{
|
||||||
modbus_msg->Func_Code += ERR_VALUES_START;
|
TrackerCnt_Warn(hmodbus->rs_err);
|
||||||
|
modbus_msg->Func_Code |= ERR_VALUES_START;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
TrackerCnt_Ok(hmodbus->rs_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -690,7 +771,15 @@ RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_ms
|
|||||||
RS_Abort(hmodbus, ABORT_TX); // if tx busy - set it free
|
RS_Abort(hmodbus, ABORT_TX); // if tx busy - set it free
|
||||||
|
|
||||||
// Transmit right there, or sets (fDeferredResponse) to transmit response in main code
|
// Transmit right there, or sets (fDeferredResponse) to transmit response in main code
|
||||||
|
if(hmodbus->f.DeferredResponse == 0)
|
||||||
|
{
|
||||||
MB_RES = RS_Handle_Transmit_Start(hmodbus, modbus_msg);
|
MB_RES = RS_Handle_Transmit_Start(hmodbus, modbus_msg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RS_Handle_Receive_Start(hmodbus, modbus_msg);
|
||||||
|
hmodbus->f.DeferredResponse = 0;
|
||||||
|
}
|
||||||
|
|
||||||
hmodbus->RS_STATUS = MB_RES;
|
hmodbus->RS_STATUS = MB_RES;
|
||||||
return MB_RES;
|
return MB_RES;
|
||||||
@@ -734,6 +823,7 @@ RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mo
|
|||||||
|
|
||||||
if (modbus_msg->ByteCnt > DATA_SIZE*2) // if ByteCnt less than DATA_SIZE
|
if (modbus_msg->ByteCnt > DATA_SIZE*2) // if ByteCnt less than DATA_SIZE
|
||||||
{
|
{
|
||||||
|
TrackerCnt_Err(hmodbus->rs_err);
|
||||||
return RS_COLLECT_MSG_ERR;
|
return RS_COLLECT_MSG_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -755,6 +845,7 @@ RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mo
|
|||||||
modbus_uart_buff[ind++] = modbus_msg->ByteCnt;
|
modbus_uart_buff[ind++] = modbus_msg->ByteCnt;
|
||||||
else // otherwise return data_size err
|
else // otherwise return data_size err
|
||||||
{
|
{
|
||||||
|
TrackerCnt_Err(hmodbus->rs_err);
|
||||||
return RS_COLLECT_MSG_ERR;
|
return RS_COLLECT_MSG_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,12 +900,21 @@ RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modb
|
|||||||
//-----INFO ABOUT DATA/MESSAGE-------
|
//-----INFO ABOUT DATA/MESSAGE-------
|
||||||
//-----------[first bits]------------
|
//-----------[first bits]------------
|
||||||
// get ID of message/user
|
// get ID of message/user
|
||||||
modbus_msg->MbAddr = modbus_uart_buff[ind++];
|
if(modbus_uart_buff[ind] != hmodbus->ID)
|
||||||
if(modbus_msg->MbAddr != hmodbus->ID)
|
{
|
||||||
|
modbus_msg->MbAddr = 0;
|
||||||
return RS_SKIP;
|
return RS_SKIP;
|
||||||
|
}
|
||||||
|
modbus_msg->MbAddr = modbus_uart_buff[ind++];
|
||||||
|
|
||||||
// get func code
|
// get func code
|
||||||
modbus_msg->Func_Code = modbus_uart_buff[ind++];
|
modbus_msg->Func_Code = modbus_uart_buff[ind++];
|
||||||
|
if(modbus_msg->Func_Code & ERR_VALUES_START) // явная херня
|
||||||
|
{
|
||||||
|
modbus_msg->MbAddr = 0;
|
||||||
|
return RS_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // if it device identification request
|
if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // if it device identification request
|
||||||
{
|
{
|
||||||
modbus_msg->DevId.MEI_Type = modbus_uart_buff[ind++];
|
modbus_msg->DevId.MEI_Type = modbus_uart_buff[ind++];
|
||||||
@@ -832,21 +932,24 @@ RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modb
|
|||||||
modbus_msg->Qnt = modbus_uart_buff[ind++] << 8;
|
modbus_msg->Qnt = modbus_uart_buff[ind++] << 8;
|
||||||
modbus_msg->Qnt |= modbus_uart_buff[ind++];
|
modbus_msg->Qnt |= modbus_uart_buff[ind++];
|
||||||
}
|
}
|
||||||
if(hmodbus->f.RX_Half == 0) // if all message received
|
|
||||||
{
|
if((hmodbus->pMessagePtr->Func_Code == 0x0F) || (hmodbus->pMessagePtr->Func_Code == 0x10))
|
||||||
|
hmodbus->pMessagePtr->ByteCnt = modbus_uart_buff[ind++];
|
||||||
|
else
|
||||||
|
hmodbus->pMessagePtr->ByteCnt = 0;
|
||||||
//---------------DATA----------------
|
//---------------DATA----------------
|
||||||
// (optional)
|
// (optional)
|
||||||
if (modbus_msg->ByteCnt != 0)
|
if (modbus_msg->ByteCnt != 0)
|
||||||
{
|
{
|
||||||
ind++; // increment ind for data_size byte
|
|
||||||
//check that data size is correct
|
//check that data size is correct
|
||||||
if (modbus_msg->ByteCnt > DATA_SIZE*2)
|
if (modbus_msg->ByteCnt > DATA_SIZE*2)
|
||||||
{
|
{
|
||||||
modbus_msg->Func_Code += ERR_VALUES_START;
|
TrackerCnt_Err(hmodbus->rs_err);
|
||||||
|
modbus_msg->Func_Code |= ERR_VALUES_START;
|
||||||
return RS_PARSE_MSG_ERR;
|
return RS_PARSE_MSG_ERR;
|
||||||
}
|
}
|
||||||
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA;
|
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA;
|
||||||
for(int i = 0; i < modbus_msg->ByteCnt; i++) // /2 because we transmit 8 bits, not 16 bits
|
for(int i = 0; i < modbus_msg->ByteCnt; i++)
|
||||||
{ // set data
|
{ // set data
|
||||||
if (i%2 == 0)
|
if (i%2 == 0)
|
||||||
*tmp_data_addr = ((uint16_t)modbus_uart_buff[ind++] << 8);
|
*tmp_data_addr = ((uint16_t)modbus_uart_buff[ind++] << 8);
|
||||||
@@ -868,20 +971,19 @@ RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modb
|
|||||||
// compare crc
|
// compare crc
|
||||||
if (modbus_msg->MB_CRC != CRC_VALUE)
|
if (modbus_msg->MB_CRC != CRC_VALUE)
|
||||||
{
|
{
|
||||||
modbus_msg->Func_Code += ERR_VALUES_START;
|
TrackerCnt_Err(hmodbus->rs_err);
|
||||||
|
modbus_msg->Func_Code |= ERR_VALUES_START;
|
||||||
}
|
}
|
||||||
// hmodbus->MB_RESPONSE = MB_CRC_ERR; // set func code - error about wrong crc
|
// hmodbus->MB_RESPONSE = MB_CRC_ERR; // set func code - error about wrong crc
|
||||||
|
|
||||||
// check is buffer empty
|
// check is buffer empty
|
||||||
check_empty_buff = 0;
|
check_empty_buff = 0;
|
||||||
for(int i=0; i<ind;i++)
|
for(int i=0; i<ind;i++)
|
||||||
check_empty_buff += modbus_uart_buff[i];
|
check_empty_buff += modbus_uart_buff[i];
|
||||||
// if(check_empty_buff == 0)
|
// if(check_empty_buff == 0)
|
||||||
// hmodbus->MB_RESPONSE = MB_EMPTY_MSG; //
|
// hmodbus->MB_RESPONSE = MB_EMPTY_MSG; //
|
||||||
}
|
|
||||||
|
|
||||||
return RS_OK;
|
return RS_OK;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -896,8 +998,8 @@ RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hmodbus, uint32_
|
|||||||
RS_StatusTypeDef MB_RES = 0;
|
RS_StatusTypeDef MB_RES = 0;
|
||||||
|
|
||||||
MB_RES = RS_Parse_Message(hmodbus, hmodbus->pMessagePtr, hmodbus->pBufferPtr);
|
MB_RES = RS_Parse_Message(hmodbus, hmodbus->pMessagePtr, hmodbus->pBufferPtr);
|
||||||
if(MB_RES == RS_SKIP) // if message not for us
|
// if(MB_RES == RS_SKIP) // if message not for us
|
||||||
return MB_RES; // return
|
// return MB_RES; // return
|
||||||
|
|
||||||
|
|
||||||
if ((hmodbus->pMessagePtr->Func_Code & ~ERR_VALUES_START) < 0x0F)
|
if ((hmodbus->pMessagePtr->Func_Code & ~ERR_VALUES_START) < 0x0F)
|
||||||
@@ -923,28 +1025,16 @@ RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hmodbus, uint32_
|
|||||||
return RS_OK;
|
return RS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------FOR USER------------------------------
|
|
||||||
//-------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
void MB_DeviceInentificationInit(void)
|
||||||
void MB_DevoceInentificationInit(void)
|
|
||||||
{
|
{
|
||||||
MB_INFO.VendorName.name = MODBUS_VENDOR_NAME;
|
MB_ObjectInit(&MB_DEVID.VendorName, MODBUS_VENDOR_NAME);
|
||||||
MB_INFO.ProductCode.name = MODBUS_PRODUCT_CODE;
|
MB_ObjectInit(&MB_DEVID.ProductCode, MODBUS_PRODUCT_CODE);
|
||||||
MB_INFO.Revision.name = MODBUS_REVISION;
|
MB_ObjectInit(&MB_DEVID.Revision, MODBUS_REVISION);
|
||||||
MB_INFO.VendorUrl.name = MODBUS_VENDOR_URL;
|
MB_ObjectInit(&MB_DEVID.VendorUrl, MODBUS_VENDOR_URL);
|
||||||
MB_INFO.ProductName.name = MODBUS_PRODUCT_NAME;
|
MB_ObjectInit(&MB_DEVID.ProductName, MODBUS_PRODUCT_NAME);
|
||||||
MB_INFO.ModelName.name = MODBUS_MODEL_NAME;
|
MB_ObjectInit(&MB_DEVID.ModelName, MODBUS_MODEL_NAME);
|
||||||
MB_INFO.UserApplicationName.name = MODBUS_USER_APPLICATION_NAME;
|
|
||||||
|
|
||||||
|
|
||||||
MB_INFO.VendorName.length = sizeof(MODBUS_VENDOR_NAME);
|
|
||||||
MB_INFO.ProductCode.length = sizeof(MODBUS_PRODUCT_CODE);
|
|
||||||
MB_INFO.Revision.length = sizeof(MODBUS_REVISION);
|
|
||||||
MB_INFO.VendorUrl.length = sizeof(MODBUS_VENDOR_URL);
|
|
||||||
MB_INFO.ProductName.length = sizeof(MODBUS_PRODUCT_NAME);
|
|
||||||
MB_INFO.ModelName.length = sizeof(MODBUS_MODEL_NAME);
|
|
||||||
MB_INFO.UserApplicationName.length = sizeof(MODBUS_USER_APPLICATION_NAME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
144
Modbus/modbus.h
144
Modbus/modbus.h
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#include "modbus_config.h"
|
#include "modbus_config.h"
|
||||||
#include "modbus_data.h"
|
#include "modbus_data.h"
|
||||||
//#include "settings.h" // for modbus settings
|
#include "__crc_algs.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup MODBUS_SETTINGS
|
* @addtogroup MODBUS_SETTINGS
|
||||||
@@ -25,11 +25,17 @@
|
|||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////---SETTINGS---/////////////////////////////
|
//////////////////////////---SETTINGS---/////////////////////////////
|
||||||
// USER SETTINGS FOR MODBUS IN interface_config.h
|
// USER SETTINGS FOR MODBUS IN interface_config.h
|
||||||
|
/**
|
||||||
|
* @brief Поменять комманды 0x03 и 0x04 местами (для LabView терминалки от двигателей)
|
||||||
|
* @details Терминалка от двигателей использует для чтения регистров комманду R_HOLD_REGS вместо R_IN_REGS
|
||||||
|
* Поэтому чтобы считывать Input Regs - надо поменять их местами.
|
||||||
|
*/
|
||||||
|
//#define MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS
|
||||||
//////////////////////////---SETTINGS---/////////////////////////////
|
//////////////////////////---SETTINGS---/////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
/////////////////////---USER MESSAGE DEFINES---//////////////////////
|
////////////////////---MODBUS MESSAGE DEFINES---/////////////////////
|
||||||
//-------------DEFINES FOR STRUCTURE----------------
|
//-------------DEFINES FOR STRUCTURE----------------
|
||||||
/* defines for structure of modbus message */
|
/* defines for structure of modbus message */
|
||||||
#define MbAddr_SIZE 1 ///< size of (MbAddr)
|
#define MbAddr_SIZE 1 ///< size of (MbAddr)
|
||||||
@@ -86,7 +92,8 @@ typedef enum //MB_FunctonTypeDef
|
|||||||
MB_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек
|
MB_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек
|
||||||
MB_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров
|
MB_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров
|
||||||
|
|
||||||
MB_R_DEVICE_INFO = 0x2B, ///< Чтения информации об устройстве
|
MB_R_DIAGNOSTIC = 0x08, ///< Чтение диагностической информации устройства
|
||||||
|
MB_R_DEVICE_INFO = 0x2B, ///< Чтение информации об устройстве
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
// error reading
|
// error reading
|
||||||
@@ -100,24 +107,63 @@ typedef enum //MB_FunctonTypeDef
|
|||||||
MB_ERR_W_HOLD_REG = MB_W_HOLD_REG + ERR_VALUES_START, ///< Ошибка записи одиночного регистра
|
MB_ERR_W_HOLD_REG = MB_W_HOLD_REG + ERR_VALUES_START, ///< Ошибка записи одиночного регистра
|
||||||
MB_ERR_W_COILS = MB_W_COILS + ERR_VALUES_START, ///< Ошибка записи нескольких битовых ячеек
|
MB_ERR_W_COILS = MB_W_COILS + ERR_VALUES_START, ///< Ошибка записи нескольких битовых ячеек
|
||||||
MB_ERR_W_HOLD_REGS = MB_W_HOLD_REGS + ERR_VALUES_START, ///< Ошибка записи нескольких регистров
|
MB_ERR_W_HOLD_REGS = MB_W_HOLD_REGS + ERR_VALUES_START, ///< Ошибка записи нескольких регистров
|
||||||
|
|
||||||
|
MB_ERR_R_DIAGNOSTIC = MB_R_DIAGNOSTIC + ERR_VALUES_START, ///< Ошибка чтения диагностической информации устройства
|
||||||
|
MB_ERR_R_DEVICE_INFO = MB_R_DEVICE_INFO + ERR_VALUES_START, ///< Ошибка чтения информации об устройстве
|
||||||
}MB_FunctonTypeDef;
|
}MB_FunctonTypeDef;
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief Structure for modbus diagnostics sub-functions codes */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
RETURN_QUERRY_DATA = 0x0,
|
||||||
|
RESTART_COMM_OPTIONS = 0x1,
|
||||||
|
RETURN_DIAG_REG = 0x2,
|
||||||
|
CHANGE_ASCII_INPUT_DELIMITER = 0x3,
|
||||||
|
FORCE_LISTEN_ONLY_MODE = 0x4,
|
||||||
|
CLEAR_CNT_AND_DIAG_REG = 0xA,
|
||||||
|
RETURN_BUS_MSG_CNT = 0xB,
|
||||||
|
RETURN_BUS_COMM_ERR_CNT = 0xC,
|
||||||
|
RETURN_BUS_EXCEPT_ERR_CNT = 0xD,
|
||||||
|
RETURN_SLAVE_MSG_CNT = 0xE,
|
||||||
|
RETURN_SLAVE_NO_RESP_CNT = 0xF,
|
||||||
|
RETURN_SLAVE_NAK_CNT = 0x10,
|
||||||
|
RETURN_SLAVE_BUSY_CNT = 0x11,
|
||||||
|
RETURN_BUS_CHAR_OVERRUN = 0x12,
|
||||||
|
CLEAR_OVR_CNT_AND_FLAG = 0x12,
|
||||||
|
}MB_DiagnosticsSubFunctionTypeDef;
|
||||||
|
|
||||||
|
|
||||||
/** @brief Structure for MEI func codes */
|
/** @brief Structure for MEI func codes */
|
||||||
typedef enum //MB_FunctonTypeDef
|
typedef enum //MB_FunctonTypeDef
|
||||||
{
|
{
|
||||||
MEI_DEVICE_IDENTIFICATION = 0x0E,
|
MEI_DEVICE_IDENTIFICATION = 0x0E,
|
||||||
}MB_MEITypeDef;
|
}MB_MEITypeDef;
|
||||||
|
|
||||||
/** @brief Structure for MEI func codes */
|
/** @brief Structure for comformity */
|
||||||
typedef enum //MB_FunctonTypeDef
|
typedef enum //MB_FunctonTypeDef
|
||||||
{
|
{
|
||||||
MB_BASIC_IDENTIFICATION = 0x01,
|
MB_BASIC_IDENTIFICATION = 0x01, /*!< @brief Basic Device Identification.
|
||||||
MB_REGULAR_IDENTIFICATION = 0x02,
|
@details All objects of this category are mandatory:
|
||||||
|
VendorName,Product code, and revision number */
|
||||||
|
|
||||||
|
MB_REGULAR_IDENTIFICATION = 0x02, /*!< @brief Regular Device Identification.
|
||||||
|
@details The device provides additional and optional
|
||||||
|
identification and description data objects */
|
||||||
|
|
||||||
|
MB_EXTENDED_IDENTIFICATION = 0x03, /*!< @brief Extended Device Identification.
|
||||||
|
@details The device provides additional and optional
|
||||||
|
identification and description private data about the physical
|
||||||
|
device itself. All of these data are device dependent. */
|
||||||
|
|
||||||
|
MB_SPEDIFIC_IDENTIFICATION = 0x04, /*!< @brief Specific Device Identification.
|
||||||
|
@details The device provides one specific identification object. */
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
MB_ERR_BASIC_IDENTIFICATION = MB_BASIC_IDENTIFICATION + ERR_VALUES_START,
|
MB_ERR_BASIC_IDENTIFICATION = MB_BASIC_IDENTIFICATION + ERR_VALUES_START,
|
||||||
MB_ERR_REGULAR_IDENTIFICATION = MB_REGULAR_IDENTIFICATION + ERR_VALUES_START,
|
MB_ERR_REGULAR_IDENTIFICATION = MB_REGULAR_IDENTIFICATION + ERR_VALUES_START,
|
||||||
|
MB_ERR_EXTENDED_IDENTIFICATION = MB_REGULAR_IDENTIFICATION + ERR_VALUES_START,
|
||||||
|
MB_ERR_SPEDIFIC_IDENTIFICATION = MB_REGULAR_IDENTIFICATION + ERR_VALUES_START,
|
||||||
}MB_ConformityTypeDef;
|
}MB_ConformityTypeDef;
|
||||||
|
|
||||||
/** @brief Structure for decive identification message type */
|
/** @brief Structure for decive identification message type */
|
||||||
@@ -126,11 +172,12 @@ typedef struct
|
|||||||
MB_MEITypeDef MEI_Type; ///< MEI Type assigned number for Device Identification Interface
|
MB_MEITypeDef MEI_Type; ///< MEI Type assigned number for Device Identification Interface
|
||||||
MB_ConformityTypeDef ReadDevId;
|
MB_ConformityTypeDef ReadDevId;
|
||||||
MB_ConformityTypeDef Conformity;
|
MB_ConformityTypeDef Conformity;
|
||||||
uint8_t MoreFollows; ///< in this library always a zero
|
uint8_t MoreFollows;
|
||||||
uint8_t NextObjId;
|
uint8_t NextObjId;
|
||||||
uint8_t NumbOfObj;
|
uint8_t NumbOfObj;
|
||||||
}MB_DevIdMsgTypeDef;
|
}MB_DevIdMsgTypeDef;
|
||||||
|
|
||||||
|
|
||||||
/** @brief Structure for modbus messsage */
|
/** @brief Structure for modbus messsage */
|
||||||
typedef struct // RS_MsgTypeDef
|
typedef struct // RS_MsgTypeDef
|
||||||
{
|
{
|
||||||
@@ -148,15 +195,69 @@ typedef struct // RS_MsgTypeDef
|
|||||||
}RS_MsgTypeDef;
|
}RS_MsgTypeDef;
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
extern RS_MsgTypeDef MODBUS_MSG;
|
extern RS_MsgTypeDef MODBUS_MSG;
|
||||||
/////////////////////---MODBUS USER SETTINGS---//////////////////////
|
////////////////////---MODBUS MESSAGE DEFINES---/////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
///////////////---DEVICE IDENTIVICATIONS DEFINES---//////////////////
|
||||||
|
|
||||||
|
/** @brief Структура для объекта (идентификатора устройства модбас) */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned length;
|
||||||
|
char *name;
|
||||||
|
}MB_DeviceObjectTypeDef;
|
||||||
|
|
||||||
|
/** @brief Структура со идентификаторами устройства модбас */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
MB_DeviceObjectTypeDef VendorName;
|
||||||
|
MB_DeviceObjectTypeDef ProductCode;
|
||||||
|
MB_DeviceObjectTypeDef Revision;
|
||||||
|
MB_DeviceObjectTypeDef VendorUrl;
|
||||||
|
MB_DeviceObjectTypeDef ProductName;
|
||||||
|
MB_DeviceObjectTypeDef ModelName;
|
||||||
|
MB_DeviceObjectTypeDef UserApplicationName;
|
||||||
|
|
||||||
|
MB_DeviceObjectTypeDef Reserved[0x79];
|
||||||
|
|
||||||
|
MB_DeviceObjectTypeDef User[MODBUS_NUMB_OF_USEROBJECTS];
|
||||||
|
}MB_DeviceIdentificationTypeDef;
|
||||||
|
extern MB_DeviceIdentificationTypeDef MB_DEVID;
|
||||||
|
void MB_DeviceInentificationInit(void);
|
||||||
|
///////////////---DEVICE IDENTIVICATIONS DEFINES---//////////////////
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
/////////////////---DEVICE DIAGNOSTICS DEFINES---////////////////////
|
||||||
|
|
||||||
|
/** @brief Структура со диагностической информацией устройства модбас */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t DiagnosticRegister;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint16_t BusMessage;
|
||||||
|
uint16_t BusCommunicationErr;
|
||||||
|
uint16_t BusExceptionErr;
|
||||||
|
uint16_t SlaveMessage;
|
||||||
|
uint16_t SlaveNoResponse;
|
||||||
|
uint16_t SlaveNAK;
|
||||||
|
uint16_t SlaveBusy;
|
||||||
|
uint16_t BusCharacterOverrun;
|
||||||
|
}Counters;
|
||||||
|
}MB_DiagnosticsInfoTypeDef;
|
||||||
|
extern MB_DiagnosticsInfoTypeDef MB_DINFO;
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////---DEVICE DIAGNOSTICS DEFINES---////////////////////
|
||||||
/** MODBUS_SETTINGS
|
/** MODBUS_SETTINGS
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
////////////////////---MODBUS MESSAGE DEFINES---/////////////////////
|
////////////////////---MODBUS FUNCTION DEFINES---////////////////////
|
||||||
/**
|
/**
|
||||||
* @addtogroup MODBUS_MESSAGE_DEFINES
|
* @addtogroup MODBUS_MESSAGE_DEFINES
|
||||||
* @ingroup MODBUS
|
* @ingroup MODBUS
|
||||||
@@ -251,6 +352,19 @@ typedef enum
|
|||||||
* @details Позволяет обратиться к коилу по адресу относительно _arr_.
|
* @details Позволяет обратиться к коилу по адресу относительно _arr_.
|
||||||
*/
|
*/
|
||||||
#define MB_Toogle_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ^= MB_Set_Coil_Mask(_coil_)
|
#define MB_Toogle_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ^= MB_Set_Coil_Mask(_coil_)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Инициализация объектов
|
||||||
|
* @details С помозью этого дефайна инициализируются объекты в @ref MB_DeviceInentificationInit
|
||||||
|
*/
|
||||||
|
#define MB_ObjectInit(_p_obj_, _userstring_) (_p_obj_)->length = sizeof(_userstring_);\
|
||||||
|
(_p_obj_)->name = _userstring_;
|
||||||
|
/**
|
||||||
|
* @brief Инициализация пользовательских объектов
|
||||||
|
* @details С помозью этого дефайна инициализируются пользовательские объекты в MB_DeviceInentificationInit
|
||||||
|
*/
|
||||||
|
#define MB_UserObjectInit(_pinfostruct_, _user_numb_) MB_ObjectInit(&(_pinfostruct_)->User[_user_numb_], MODBUS_USEROBJECT##_user_numb_##_NAME)
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@@ -329,17 +443,19 @@ MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, u
|
|||||||
/* Define Address Origin for coils */
|
/* Define Address Origin for coils */
|
||||||
MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint16_t Qnt, uint16_t *start_shift, uint8_t WriteFlag);
|
MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint16_t Qnt, uint16_t *start_shift, uint8_t WriteFlag);
|
||||||
/* Proccess command Read Coils (01 - 0x01) */
|
/* Proccess command Read Coils (01 - 0x01) */
|
||||||
uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg);
|
uint8_t MB_Proccess_Read_Coils(RS_MsgTypeDef *modbus_msg);
|
||||||
/* Proccess command Read Holding Registers (03 - 0x03) */
|
/* Proccess command Read Holding Registers (03 - 0x03) */
|
||||||
uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg);
|
uint8_t MB_Proccess_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg);
|
||||||
/* Proccess command Read Input Registers (04 - 0x04) */
|
/* Proccess command Read Input Registers (04 - 0x04) */
|
||||||
uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg);
|
uint8_t MB_Proccess_Read_Input_Regs(RS_MsgTypeDef *modbus_msg);
|
||||||
/* Proccess command Write Single Coils (05 - 0x05) */
|
/* Proccess command Write Single Coils (05 - 0x05) */
|
||||||
uint8_t MB_Write_Single_Coil(RS_MsgTypeDef *modbus_msg);
|
uint8_t MB_Proccess_Write_Single_Coil(RS_MsgTypeDef *modbus_msg);
|
||||||
|
/* Proccess command Write Single Coils (06 - 0x06) */
|
||||||
|
uint8_t MB_Proccess_Write_Single_Reg(RS_MsgTypeDef *modbus_msg);
|
||||||
/* Proccess command Write Multiple Coils (15 - 0x0F) */
|
/* Proccess command Write Multiple Coils (15 - 0x0F) */
|
||||||
uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg);
|
uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg);
|
||||||
/* Proccess command Write Multiple Register (16 - 0x10) */
|
/* Proccess command Write Multiple Register (16 - 0x10) */
|
||||||
uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg);
|
uint8_t MB_Proccess_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg);
|
||||||
|
|
||||||
/** MODBUS_DATA_ACCESS_FUNCTIONS
|
/** MODBUS_DATA_ACCESS_FUNCTIONS
|
||||||
* @}
|
* @}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#define MODBUS_PRODUCT_NAME ""
|
#define MODBUS_PRODUCT_NAME ""
|
||||||
#define MODBUS_MODEL_NAME "STM32F103"
|
#define MODBUS_MODEL_NAME "STM32F103"
|
||||||
#define MODBUS_USER_APPLICATION_NAME ""
|
#define MODBUS_USER_APPLICATION_NAME ""
|
||||||
|
#define MODBUS_NUMB_OF_USEROBJECTS 0
|
||||||
|
|
||||||
// PERIPH FUNCTIONS AND HANDLERS
|
// PERIPH FUNCTIONS AND HANDLERS
|
||||||
#define RS_UART_Init MX_USART1_UART_Init //инициализация uart
|
#define RS_UART_Init MX_USART1_UART_Init //инициализация uart
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
*/
|
*/
|
||||||
typedef struct //MB_DataInRegsTypeDef
|
typedef struct //MB_DataInRegsTypeDef
|
||||||
{
|
{
|
||||||
|
uint16_t in[16];
|
||||||
}MB_DataInRegsTypeDef;
|
}MB_DataInRegsTypeDef;
|
||||||
|
|
||||||
|
|
||||||
@@ -52,17 +52,17 @@ typedef struct //MB_DataInRegsTypeDef
|
|||||||
*/
|
*/
|
||||||
typedef struct //MB_DataInRegsTypeDef
|
typedef struct //MB_DataInRegsTypeDef
|
||||||
{
|
{
|
||||||
|
uint16_t out[16];
|
||||||
}MB_DataHoldRegsTypeDef;
|
}MB_DataHoldRegsTypeDef;
|
||||||
|
|
||||||
|
|
||||||
// DEFINES FOR INPUT REGISTERS ARRAYS
|
// DEFINES FOR INPUT REGISTERS ARRAYS
|
||||||
#define R_INPUT_ADDR 0
|
#define R_INPUT_ADDR 0
|
||||||
#define R_INPUT_QNT 0
|
#define R_INPUT_QNT 16
|
||||||
|
|
||||||
// DEFINES FOR HOLDING REGISTERS ARRAYS
|
// DEFINES FOR HOLDING REGISTERS ARRAYS
|
||||||
#define R_HOLDING_ADDR 0
|
#define R_HOLDING_ADDR 0
|
||||||
#define R_HOLDING_QNT 0
|
#define R_HOLDING_QNT 16
|
||||||
|
|
||||||
|
|
||||||
/** MODBUS_DATA_RERISTERS_DEFINES
|
/** MODBUS_DATA_RERISTERS_DEFINES
|
||||||
@@ -128,32 +128,6 @@ typedef struct // tester modbus data
|
|||||||
extern MB_DataStructureTypeDef MB_DATA;
|
extern MB_DataStructureTypeDef MB_DATA;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Структура для объекта Modbus
|
|
||||||
* @ingroup MODBUS_DATA
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned length;
|
|
||||||
char *name;
|
|
||||||
}MB_DeviceObjectTypeDef;
|
|
||||||
/**
|
|
||||||
* @brief Структура для объектов Modbus
|
|
||||||
* @ingroup MODBUS_DATA
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
MB_DeviceObjectTypeDef VendorName;
|
|
||||||
MB_DeviceObjectTypeDef ProductCode;
|
|
||||||
MB_DeviceObjectTypeDef Revision;
|
|
||||||
MB_DeviceObjectTypeDef VendorUrl;
|
|
||||||
MB_DeviceObjectTypeDef ProductName;
|
|
||||||
MB_DeviceObjectTypeDef ModelName;
|
|
||||||
MB_DeviceObjectTypeDef UserApplicationName;
|
|
||||||
}MB_DeviceIdentificationTypeDef;
|
|
||||||
void MB_DevoceInentificationInit(void);
|
|
||||||
|
|
||||||
|
|
||||||
#endif //_MODBUS_DATA_H_
|
#endif //_MODBUS_DATA_H_
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -86,19 +86,22 @@ RS_StatusTypeDef RS_Receive_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
|
|||||||
hRS->pMessagePtr = RS_msg; // set pointer to message structire for filling it from UARTHandler fucntions
|
hRS->pMessagePtr = RS_msg; // set pointer to message structire for filling it from UARTHandler fucntions
|
||||||
|
|
||||||
// start receiving
|
// start receiving
|
||||||
uart_res = HAL_UART_Receive_IT(hRS->huart, hRS->pBufferPtr, RX_FIRST_PART_SIZE); // receive until ByteCnt+1 byte,
|
__HAL_UART_ENABLE_IT(hRS->huart, UART_IT_IDLE);
|
||||||
|
uart_res = HAL_UART_Receive_IT(hRS->huart, hRS->pBufferPtr, MSG_SIZE_MAX); // receive until ByteCnt+1 byte,
|
||||||
// then in Callback restart receive for rest bytes
|
// then in Callback restart receive for rest bytes
|
||||||
|
|
||||||
// if receive isnt started - abort RS
|
// if receive isnt started - abort RS
|
||||||
if(uart_res != HAL_OK)
|
if(uart_res != HAL_OK)
|
||||||
{
|
{
|
||||||
RS_RES = RS_Abort(hRS, ABORT_RS);
|
RS_RES = RS_Abort(hRS, ABORT_RS);
|
||||||
printf_rs_err("\n%d: Error RS: Failed to start RS receiving...", uwTick);
|
printf_rs_err("Failed to start RS receiving...");
|
||||||
|
TrackerCnt_Err(hRS->rs_err);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RS_RES = RS_OK;
|
RS_RES = RS_OK;
|
||||||
printf_rs("\n%d: RS: Start Receiving...", uwTick);
|
printf_rs("Start Receiving...");
|
||||||
|
TrackerCnt_Ok(hRS->rs_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
hRS->RS_STATUS = RS_RES;
|
hRS->RS_STATUS = RS_RES;
|
||||||
@@ -147,12 +150,14 @@ RS_StatusTypeDef RS_Transmit_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
|
|||||||
if(uart_res != HAL_OK)
|
if(uart_res != HAL_OK)
|
||||||
{
|
{
|
||||||
RS_RES = RS_Abort(hRS, ABORT_RS);
|
RS_RES = RS_Abort(hRS, ABORT_RS);
|
||||||
printf_rs_err("\n%d: Error RS: Failed to start RS transmitting...", uwTick);
|
printf_rs_err("Failed to start RS transmitting...");
|
||||||
|
TrackerCnt_Err(hRS->rs_err);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RS_RES = RS_OK;
|
RS_RES = RS_OK;
|
||||||
printf_rs("\n%d: RS: Start Transmitting...", uwTick);
|
printf_rs("Start Transmitting...");
|
||||||
|
TrackerCnt_Ok(hRS->rs_err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,11 +248,11 @@ HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huar
|
|||||||
RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode)
|
RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode)
|
||||||
{
|
{
|
||||||
HAL_StatusTypeDef uart_res = 0;
|
HAL_StatusTypeDef uart_res = 0;
|
||||||
hRS->htim->Instance->CNT = 0;
|
|
||||||
__HAL_TIM_CLEAR_IT(hRS->htim, TIM_IT_UPDATE);
|
|
||||||
|
|
||||||
if(hRS->sRS_Timeout) // if timeout setted
|
if(hRS->sRS_Timeout) // if timeout setted
|
||||||
HAL_TIM_Base_Stop_IT(hRS->htim); // stop timeout
|
HAL_TIM_Base_Stop_IT(hRS->htim); // stop timeout
|
||||||
|
hRS->htim->Instance->CNT = 0;
|
||||||
|
__HAL_TIM_CLEAR_IT(hRS->htim, TIM_IT_UPDATE);
|
||||||
|
|
||||||
if((AbortMode&ABORT_RS) == 0x00)
|
if((AbortMode&ABORT_RS) == 0x00)
|
||||||
{
|
{
|
||||||
@@ -301,6 +306,7 @@ RS_StatusTypeDef RS_Handle_Receive_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *R
|
|||||||
|
|
||||||
if(RS_RES != RS_OK)
|
if(RS_RES != RS_OK)
|
||||||
{
|
{
|
||||||
|
TrackerCnt_Err(hRS->rs_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
return RS_RES;
|
return RS_RES;
|
||||||
@@ -324,6 +330,7 @@ RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *
|
|||||||
}
|
}
|
||||||
if(RS_RES != RS_OK)
|
if(RS_RES != RS_OK)
|
||||||
{
|
{
|
||||||
|
TrackerCnt_Err(hRS->rs_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
return RS_RES;
|
return RS_RES;
|
||||||
@@ -339,6 +346,7 @@ RS_StatusTypeDef RS_UART_RxCpltCallback(RS_HandleTypeDef *hRS)
|
|||||||
{
|
{
|
||||||
RS_StatusTypeDef RS_RES = 0;
|
RS_StatusTypeDef RS_RES = 0;
|
||||||
HAL_StatusTypeDef uart_res = 0;
|
HAL_StatusTypeDef uart_res = 0;
|
||||||
|
int flag_to_response = 0;
|
||||||
|
|
||||||
// if we had received bytes before ByteCnt
|
// if we had received bytes before ByteCnt
|
||||||
if((hRS->sRS_RX_Size_Mode == RS_RX_Size_NotConst) && (hRS->f.RX_Half == 0)) // if data size isnt constant and its first half, and
|
if((hRS->sRS_RX_Size_Mode == RS_RX_Size_NotConst) && (hRS->f.RX_Half == 0)) // if data size isnt constant and its first half, and
|
||||||
@@ -349,6 +357,7 @@ RS_StatusTypeDef RS_UART_RxCpltCallback(RS_HandleTypeDef *hRS)
|
|||||||
RS_RES = RS_Define_Size_of_RX_Message(hRS, &NuRS_of_Rest_Bytes);
|
RS_RES = RS_Define_Size_of_RX_Message(hRS, &NuRS_of_Rest_Bytes);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// if we need to skip this message - restart receive
|
// if we need to skip this message - restart receive
|
||||||
if(RS_RES == RS_SKIP || NuRS_of_Rest_Bytes == 0xFFFF)
|
if(RS_RES == RS_SKIP || NuRS_of_Rest_Bytes == 0xFFFF)
|
||||||
{
|
{
|
||||||
@@ -358,39 +367,34 @@ RS_StatusTypeDef RS_UART_RxCpltCallback(RS_HandleTypeDef *hRS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if there is no bytes to receive
|
// if there is no bytes to receive
|
||||||
if(NuRS_of_Rest_Bytes == 0)
|
if(NuRS_of_Rest_Bytes != 0)
|
||||||
{
|
{
|
||||||
hRS->f.RX_Half = 0;
|
|
||||||
|
|
||||||
//---------PROCESS DATA & ENDING RECEIVING--------
|
|
||||||
RS_Set_RX_End(hRS);
|
|
||||||
|
|
||||||
if(hRS->sRS_Timeout) // if timeout setted
|
|
||||||
HAL_TIM_Base_Stop_IT(hRS->htim); // stop timeout
|
|
||||||
|
|
||||||
// parse received data
|
|
||||||
RS_RES = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr); // parse message
|
|
||||||
|
|
||||||
// RESPONSE
|
|
||||||
RS_RES = RS_Response(hRS, hRS->pMessagePtr);
|
|
||||||
return RS_RES;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------START UART RECEIVE---------------
|
//-------------START UART RECEIVE---------------
|
||||||
uart_res = HAL_UART_Receive_IT(hRS->huart, (hRS->pBufferPtr + RX_FIRST_PART_SIZE), NuRS_of_Rest_Bytes);
|
uart_res = HAL_UART_Receive_IT(hRS->huart, (hRS->pBufferPtr + RX_FIRST_PART_SIZE), NuRS_of_Rest_Bytes);
|
||||||
|
|
||||||
if(uart_res != HAL_OK)
|
if(uart_res != HAL_OK)
|
||||||
{// need uart status, so doesnt write abort to RS_RES
|
{// need uart status, so doesnt write abort to RS_RES
|
||||||
|
TrackerCnt_Err(hRS->rs_err);
|
||||||
RS_RES = RS_Abort(hRS, ABORT_RS);
|
RS_RES = RS_Abort(hRS, ABORT_RS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
RS_RES = RS_OK;
|
RS_RES = RS_OK;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hRS->f.RX_Half = 0;
|
||||||
|
flag_to_response = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
else // if we had received whole message
|
else // if we had received whole message
|
||||||
{
|
{
|
||||||
hRS->f.RX_Half = 0;
|
hRS->f.RX_Half = 0;
|
||||||
|
flag_to_response = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(flag_to_response)
|
||||||
|
{
|
||||||
//---------PROCESS DATA & ENDING RECEIVING--------
|
//---------PROCESS DATA & ENDING RECEIVING--------
|
||||||
RS_Set_RX_End(hRS);
|
RS_Set_RX_End(hRS);
|
||||||
|
|
||||||
@@ -401,8 +405,17 @@ RS_StatusTypeDef RS_UART_RxCpltCallback(RS_HandleTypeDef *hRS)
|
|||||||
RS_RES = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr); // parse message
|
RS_RES = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr); // parse message
|
||||||
|
|
||||||
// RESPONSE
|
// RESPONSE
|
||||||
|
if(RS_RES != RS_SKIP) // if message not for us
|
||||||
|
{
|
||||||
|
hRS->lastPacketTick = uwTick;
|
||||||
RS_RES = RS_Response(hRS, hRS->pMessagePtr);
|
RS_RES = RS_Response(hRS, hRS->pMessagePtr);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RS_Abort(hRS, ABORT_RX);
|
||||||
|
RS_RES = RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return RS_RES;
|
return RS_RES;
|
||||||
}
|
}
|
||||||
@@ -438,36 +451,101 @@ RS_StatusTypeDef RS_UART_TxCpltCallback(RS_HandleTypeDef *hRS)
|
|||||||
*/
|
*/
|
||||||
void RS_UART_Handler(RS_HandleTypeDef *hRS)
|
void RS_UART_Handler(RS_HandleTypeDef *hRS)
|
||||||
{
|
{
|
||||||
|
//-------------CHECK IDLE FLAG FIRST-------------
|
||||||
|
/* Проверяем флаг IDLE в первую очередь - это гарантирует обработку только после idle */
|
||||||
|
if(__HAL_UART_GET_FLAG(hRS->huart, UART_FLAG_IDLE) && __HAL_UART_GET_IT_SOURCE(hRS->huart, UART_IT_IDLE))
|
||||||
|
{
|
||||||
|
__HAL_UART_CLEAR_IDLEFLAG(hRS->huart); // Важно: очистить флаг IDLE
|
||||||
|
|
||||||
|
// Если прием активен и мы получили IDLE - это конец фрейма
|
||||||
|
if(RS_Is_RX_Busy(hRS) && hRS->f.RX_Ongoing)
|
||||||
|
{
|
||||||
|
// Останавливаем таймаут
|
||||||
|
if(hRS->sRS_Timeout)
|
||||||
|
HAL_TIM_Base_Stop_IT(hRS->htim);
|
||||||
|
|
||||||
|
// Получаем количество фактически принятых байтов
|
||||||
|
uint16_t received_bytes = hRS->huart->RxXferSize - hRS->huart->RxXferCount;
|
||||||
|
|
||||||
|
if(received_bytes > 0)
|
||||||
|
{
|
||||||
|
// Принудительно завершаем прием (IDLE прервал наш прием)
|
||||||
|
RS_Abort(hRS, ABORT_RX);
|
||||||
|
|
||||||
|
// Устанавливаем фактический размер данных
|
||||||
|
hRS->RS_Message_Size = received_bytes;
|
||||||
|
|
||||||
|
// Завершаем прием в нашей структуре
|
||||||
|
RS_Set_RX_End(hRS);
|
||||||
|
|
||||||
|
// Проверяем адрес Modbus перед обработкой
|
||||||
|
if(hRS->pBufferPtr[0] != hRS->ID)
|
||||||
|
{
|
||||||
|
// Чужое сообщение - игнорируем и начинаем новый прием
|
||||||
|
RS_Abort(hRS, ABORT_RX);
|
||||||
|
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Парсим наше сообщение
|
||||||
|
RS_StatusTypeDef parse_res = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr);
|
||||||
|
|
||||||
|
// RESPONSE
|
||||||
|
if(parse_res != RS_SKIP)
|
||||||
|
{
|
||||||
|
hRS->lastPacketTick = uwTick;
|
||||||
|
RS_Response(hRS, hRS->pMessagePtr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RS_Abort(hRS, ABORT_RX);
|
||||||
|
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// IDLE без данных - просто перезапускаем прием
|
||||||
|
RS_Abort(hRS, ABORT_RX);
|
||||||
|
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return; // Выходим после обработки IDLE
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------STANDARD UART HANDLING-------------
|
||||||
|
HAL_UART_IRQHandler(hRS->huart);
|
||||||
|
|
||||||
//-------------CALL RS CALLBACKS------------
|
//-------------CALL RS CALLBACKS------------
|
||||||
/* IF NO ERROR OCCURS */
|
/* IF NO ERROR OCCURS */
|
||||||
if(hRS->huart->ErrorCode == 0)
|
if(hRS->huart->ErrorCode == 0)
|
||||||
{
|
{
|
||||||
hRS->htim->Instance->CNT = 0; // reset cnt;
|
hRS->htim->Instance->CNT = 0; // reset cnt;
|
||||||
/* Start timeout */
|
|
||||||
|
/* Start timeout при получении первого байта */
|
||||||
if(hRS->sRS_Timeout) // if timeout setted
|
if(hRS->sRS_Timeout) // if timeout setted
|
||||||
if((hRS->huart->RxXferCount+1 == hRS->huart->RxXferSize) && RS_Is_RX_Busy(hRS)) // if first byte is received and receive is active
|
if((hRS->huart->RxXferCount+1 == hRS->huart->RxXferSize) && RS_Is_RX_Busy(hRS)) // if first byte is received and receive is active
|
||||||
{
|
{
|
||||||
hRS->htim->Instance->ARR = hRS->sRS_Timeout; // reset cnt;
|
|
||||||
HAL_TIM_Base_Start_IT(hRS->htim);
|
HAL_TIM_Base_Start_IT(hRS->htim);
|
||||||
RS_Set_RX_Active_Flags(hRS);
|
RS_Set_RX_Active_Flags(hRS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RX Callback */
|
/* RX Callback - теперь НЕ вызываем здесь, ждем IDLE */
|
||||||
if (( hRS->huart->RxXferCount == 0U) && RS_Is_RX_Busy(hRS) && // if all bytes are received and receive is active
|
|
||||||
hRS->huart->RxState != HAL_UART_STATE_BUSY_RX) // also check that receive "REALLY" isnt busy
|
|
||||||
RS_UART_RxCpltCallback(hRS);
|
|
||||||
|
|
||||||
/* TX Callback */
|
/* TX Callback - оставляем без изменений */
|
||||||
if (( hRS->huart->TxXferCount == 0U) && RS_Is_TX_Busy(hRS) && // if all bytes are transmited and transmit is active
|
if ((hRS->huart->TxXferCount == 0U) && RS_Is_TX_Busy(hRS) && // if all bytes are transmited and transmit is active
|
||||||
hRS->huart->gState != HAL_UART_STATE_BUSY_TX) // also check that receive "REALLY" isnt busy
|
hRS->huart->gState != HAL_UART_STATE_BUSY_TX) // also check that receive "REALLY" isnt busy
|
||||||
RS_UART_TxCpltCallback(hRS);
|
RS_UART_TxCpltCallback(hRS);
|
||||||
|
|
||||||
|
/* NOTE: RX Callback больше не вызывается здесь - ждем IDLE для гарантии конца фрейма */
|
||||||
}
|
}
|
||||||
//----------------ERRORS HANDLER----------------
|
//----------------ERRORS HANDLER----------------
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
//TrackerCnt_Err(hRS->rs_err);
|
||||||
/* de-init uart transfer */
|
/* de-init uart transfer */
|
||||||
RS_Abort(hRS, ABORT_RS);
|
RS_Abort(hRS, ABORT_RS);
|
||||||
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
|
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
|
||||||
|
|
||||||
// later, maybe, will be added specific handlers for err
|
// later, maybe, will be added specific handlers for err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -481,9 +559,12 @@ void RS_UART_Handler(RS_HandleTypeDef *hRS)
|
|||||||
*/
|
*/
|
||||||
void RS_TIM_Handler(RS_HandleTypeDef *hRS)
|
void RS_TIM_Handler(RS_HandleTypeDef *hRS)
|
||||||
{
|
{
|
||||||
|
HAL_TIM_IRQHandler(hRS->htim);
|
||||||
|
|
||||||
HAL_TIM_Base_Stop_IT(hRS->htim);
|
HAL_TIM_Base_Stop_IT(hRS->htim);
|
||||||
RS_Abort(hRS, ABORT_RS);
|
RS_Abort(hRS, ABORT_RS);
|
||||||
|
if(hRS->pMessagePtr->MbAddr == hRS->ID) // ошибка если таймаут по нашему сообщению
|
||||||
|
TrackerCnt_Err(hRS->rs_err);
|
||||||
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
|
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
|
||||||
}
|
}
|
||||||
//--------------------CALLBACK/HANDLER FUNCTIONS---------------------
|
//--------------------CALLBACK/HANDLER FUNCTIONS---------------------
|
||||||
|
|||||||
@@ -27,9 +27,6 @@
|
|||||||
|
|
||||||
#include "modbus.h"
|
#include "modbus.h"
|
||||||
|
|
||||||
#include "crc_algs.h"
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
////////////////////////////---DEFINES---////////////////////////////
|
////////////////////////////---DEFINES---////////////////////////////
|
||||||
/* Check that all defines required by RS are defined */
|
/* Check that all defines required by RS are defined */
|
||||||
@@ -73,13 +70,51 @@
|
|||||||
#define RS_Is_RX_Busy(_hRS_) (_hRS_->f.RX_Busy == 1)
|
#define RS_Is_RX_Busy(_hRS_) (_hRS_->f.RX_Busy == 1)
|
||||||
#define RS_Is_TX_Busy(_hRS_) (_hRS_->f.TX_Busy == 1)
|
#define RS_Is_TX_Busy(_hRS_) (_hRS_->f.TX_Busy == 1)
|
||||||
|
|
||||||
|
// Заглушки
|
||||||
|
// направление передачи rs485
|
||||||
#ifndef RS_EnableReceive
|
#ifndef RS_EnableReceive
|
||||||
#define RS_EnableReceive()
|
#define RS_EnableReceive()
|
||||||
#endif
|
#endif
|
||||||
#ifndef RS_EnableTransmit
|
#ifndef RS_EnableTransmit
|
||||||
#define RS_EnableTransmit()
|
#define RS_EnableTransmit()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __MYLIBS_INCLUDE_H_
|
||||||
|
// дефайны из mylibs include
|
||||||
|
static int dummy;
|
||||||
|
#define TrackerTypeDef(num_user_vars) void *
|
||||||
|
#define num_of_usercnts(_user_) 0
|
||||||
|
#define assert_tracecnt(_cntstruct_, _uservarnumb_) 0
|
||||||
|
#define if_assert_usertracker(_cntstruct_, _uservarnumb_) if(0)
|
||||||
|
#define tern_assert_usertracker(_cntstruct_, _uservarnumb_) 0
|
||||||
|
#define TrackerGet_Ok(_cntstruct_) dummy
|
||||||
|
#define TrackerGet_Err(_cntstruct_) dummy
|
||||||
|
#define TrackerGet_Warn(_cntstruct_) dummy
|
||||||
|
#define TrackerGet_User(_cntstruct_, _uservarnumb_) dummy
|
||||||
|
#define TrackerCnt_Ok(_cntstruct_)
|
||||||
|
#define TrackerCnt_Err(_cntstruct_)
|
||||||
|
#define TrackerCnt_Warn(_cntstruct_)
|
||||||
|
#define TrackerCnt_User(_cntstruct_, _uservarnumb_)
|
||||||
|
#define TrackerWrite_User(_cntstruct_, _uservarnumb_, _val_)
|
||||||
|
#define TrackerClear_All(_cntstruct_)
|
||||||
|
#define TrackerClear_Ok(_cntstruct_)
|
||||||
|
#define TrackerClear_Err(_cntstruct_)
|
||||||
|
#define TrackerClear_Warn(_cntstruct_)
|
||||||
|
#define TrackerClear_User(_cntstruct_)
|
||||||
|
#define TrackerClear_UserAll(_cntstruct_)
|
||||||
|
|
||||||
|
#ifndef printf_rs_err
|
||||||
|
#define printf_rs_err(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef printf_rs
|
||||||
|
#define printf_rs(...)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RS_USER_VARS_NUMB
|
||||||
|
#define RS_USER_VARS_NUMB 0
|
||||||
|
#endif
|
||||||
////////////////////////////---DEFINES---////////////////////////////
|
////////////////////////////---DEFINES---////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
@@ -156,6 +191,7 @@ typedef struct
|
|||||||
unsigned MessageHandled:1; ///< flag: 1 - RS command is handled, 0 - RS command isnt handled yet
|
unsigned MessageHandled:1; ///< flag: 1 - RS command is handled, 0 - RS command isnt handled yet
|
||||||
unsigned EchoResponse:1; ///< flag: 1 - response with received msg, 0 - response with own msg
|
unsigned EchoResponse:1; ///< flag: 1 - response with received msg, 0 - response with own msg
|
||||||
unsigned DeferredResponse:1; ///< flag: 1 - response not in interrupt, 0 - response in interrupt
|
unsigned DeferredResponse:1; ///< flag: 1 - response not in interrupt, 0 - response in interrupt
|
||||||
|
unsigned DataUpdated:1; ///< flag: 1 - Received command to write colis/resg
|
||||||
unsigned ReInit_UART:1; ///< flag: 1 - need to reinitialize uart, 0 - nothing
|
unsigned ReInit_UART:1; ///< flag: 1 - need to reinitialize uart, 0 - nothing
|
||||||
}RS_FlagsTypeDef;
|
}RS_FlagsTypeDef;
|
||||||
|
|
||||||
@@ -185,7 +221,10 @@ typedef struct // RS_HandleTypeDef
|
|||||||
RS_FlagsTypeDef f; ///< These flags for controling receive/transmit
|
RS_FlagsTypeDef f; ///< These flags for controling receive/transmit
|
||||||
|
|
||||||
/* RS STATUS */
|
/* RS STATUS */
|
||||||
|
uint32_t lastPacketTick;
|
||||||
RS_StatusTypeDef RS_STATUS; ///< RS status
|
RS_StatusTypeDef RS_STATUS; ///< RS status
|
||||||
|
|
||||||
|
TrackerTypeDef(RS_USER_VARS_NUMB) rs_err;
|
||||||
}RS_HandleTypeDef;
|
}RS_HandleTypeDef;
|
||||||
extern RS_HandleTypeDef hmodbus1;
|
extern RS_HandleTypeDef hmodbus1;
|
||||||
|
|
||||||
@@ -247,11 +286,5 @@ void RS_TIM_Handler(RS_HandleTypeDef *hRS);
|
|||||||
///////////////////////////---FUNCTIONS---///////////////////////////
|
///////////////////////////---FUNCTIONS---///////////////////////////
|
||||||
|
|
||||||
|
|
||||||
#ifndef printf_rs_err
|
|
||||||
#define printf_rs_err(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef printf_rs
|
|
||||||
#define printf_rs(...)
|
|
||||||
#endif
|
|
||||||
#endif // __RS_LIB_H_
|
#endif // __RS_LIB_H_
|
||||||
|
|||||||
Reference in New Issue
Block a user