diff --git a/crc_algs.cpp b/crc_algs.cpp index fcfa779..ea5dd8c 100644 --- a/crc_algs.cpp +++ b/crc_algs.cpp @@ -1,4 +1,4 @@ -#include "crc_algs.h" +#include "modbus/crc_algs.h" uint32_t CRC_calc; @@ -16,40 +16,40 @@ unsigned uIndex; uint32_t crc32(uint8_t *data, uint32_t data_size) { - static const unsigned int crc32_table[] = + 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 + 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--) @@ -62,55 +62,55 @@ unsigned int 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; +{ + /*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]; + uchCRCLo = auchCRCLo[uIndex]; } - return uchCRCHi | uchCRCLo<<8; + return uchCRCHi | uchCRCLo<<8; } diff --git a/modbus.cpp b/modbus.cpp index 8b54355..27c6a26 100644 --- a/modbus.cpp +++ b/modbus.cpp @@ -1,8 +1,8 @@ /** ************************************************************************** -* @file modbus.cpp -* @brief Модуль для реализации MODBUS. -************************************************************************** +* @file modbus.cpp +* @brief Модуль для реализации MODBUS. +************************************************************************** * @details Файл содержит реализацию функций работы с Modbus, включая: * - доступ к coils и registers; * - обработку команд протокола; @@ -11,6 +11,9 @@ * * @section Функции и макросы * +* ### Инициализация: +* - MODBUS_FirstInit() — Инициализация модуля Modbus. +* * ### Доступ к coils: * - MB_Set_Coil_Local() — Установить coil по локальному адресу. * - MB_Reset_Coil_Local() — Сбросить coil по локальному адресу. @@ -36,37 +39,41 @@ * - RS_Define_Size_of_RX_Message() — Определение размера принимаемого сообщения. * - RS_Init() — Инициализация UART. * -* ### Инициализация: -* - MODBUS_FirstInit() — Инициализация модуля Modbus. * * @section Структура данных Modbus * * #### Holding/Input Registers: -* - Регистры — 16-битные слова. Доступ к регистрам осуществляется через указатель. +* - Регистры — 16-битные слова. Доступ к регистрам осуществляется через указатель. * Таким образом, сами регистры могут представлять собой как массив так и структуру. * * #### Coils: -* - Coils — это биты, упакованные в 16-битные слова. Доступ к коилам осуществляется через указатель. +* - Coils — это биты, упакованные в 16-битные слова. Доступ к коилам осуществляется через указатель. * Таким образом, сами коилы могут представлять собой как массив так и структуру. * * @section Инструкция по подключению * Настройте modbus_config.h дефайны для нужной работы UART * -* После для запуска Modbus: +* Минимум для запуска Modbus: * @verbatim - //----------------Прием модбас----------------// #include "rs_message.h" MODBUS_FirstInit(); - void loop() - { - RS_Process(&hmodbus1);(&hmodbus1, &MODBUS_MSG); - } + void loop() + { + RS_Process(&hmodbus1); + } +* @endverbatim +* Для RTOS: +* @verbatim + #include "rs_message.h" + MODBUS_FirstInit(); + + xTaskCreatePinnedToCore(RS_Task, "Modbus", 4096, &hmodbus1, 2, NULL, 1); * @endverbatim * ******************************************************************************/ -#include "crc_algs.h" -#include "rs_message.h" +#include "modbus/crc_algs.h" +#include "modbus/rs_message.h" uint32_t dbg_temp, dbg_temp2, dbg_temp3; // for debug RS_HandleTypeDef hmodbus1; @@ -79,482 +86,482 @@ RS_MsgTypeDef MODBUS_MSG; //------------------------------------------------------------------- //-----------------------------FOR USER------------------------------ /** - * @brief First set up of MODBUS. - * @details Первый инит модбас. Заполняет структуры и инициализирует таймер и юарт для общения по модбас. - * @note This called from main - */ + * @brief First set up of MODBUS. + * @details Первый инит модбас. Заполняет структуры и инициализирует таймер и юарт для общения по модбас. + * @note This called from main + */ void MODBUS_FirstInit(void) { MB_DevoceInentificationInit(); - //-----------SETUP MODBUS------------- - hmodbus1.ID = MODBUS_DEVICE_ID; + //-----------SETUP MODBUS------------- + hmodbus1.ID = MODBUS_DEVICE_ID; hmodbus1.sRS_Timeout = MODBUS_TIMEOUT; - hmodbus1.sRS_Mode = SLAVE_ALWAYS_WAIT; - hmodbus1.sRS_RX_Size_Mode = RS_RX_Size_NotConst; - hmodbus1.pMessagePtr = &MODBUS_MSG; - hmodbus1.rx_pin = MODBUS_RX_PIN; - hmodbus1.tx_pin = MODBUS_TX_PIN; - hmodbus1.taskDelay = RS_IN_FREERTOS; - // INIT - hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &rs_huart, MODBUS_SPEED, 0); + hmodbus1.sRS_Mode = SLAVE_ALWAYS_WAIT; + hmodbus1.sRS_RX_Size_Mode = RS_RX_Size_NotConst; + hmodbus1.pMessagePtr = &MODBUS_MSG; + hmodbus1.rx_pin = MODBUS_RX_PIN; + hmodbus1.tx_pin = MODBUS_TX_PIN; + hmodbus1.taskDelay = RS_IN_RTOS; + // INIT + hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &rs_huart, MODBUS_SPEED, 0); - RS_EnableReceive(); + RS_EnableReceive(); } /** - * @brief Set or Reset Coil at its global address. - * @param Addr - адрес коила. - * @param WriteVal - Что записать в коил: 0 или 1. - * @return ExceptionCode - Код исключения если коила по адресу не существует, и NO_ERRORS если все ок. - * - * @details Позволяет обратиться к любому коилу по его глобальному адрессу. - Вне зависимости от того как коилы размещены в памяти. - */ + * @brief Set or Reset Coil at its global address. + * @param Addr - адрес коила. + * @param WriteVal - Что записать в коил: 0 или 1. + * @return ExceptionCode - Код исключения если коила по адресу не существует, и NO_ERRORS если все ок. + * + * @details Позволяет обратиться к любому коилу по его глобальному адрессу. + Вне зависимости от того как коилы размещены в памяти. + */ MB_ExceptionTypeDef MB_Write_Coil_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal) { - //---------CHECK FOR ERRORS---------- - MB_ExceptionTypeDef Exception = NO_ERRORS; - uint16_t *coils; - uint16_t start_shift = 0; // shift in coils register - - //------------WRITE COIL------------- - Exception = MB_DefineCoilsAddress(&coils, Addr, 1, &start_shift, 1); - if(Exception == NO_ERRORS) - { - switch(WriteVal) - { - case SET_COIL: - *coils |= (1<= R_ARR_ADDR) - { - // if quantity too big return error - if ((Addr - R_ARR_ADDR) + Qnt > R_ARR_NUMB) - { - MB_DEBUG_PRINT("[MB] Illegal Data Address"); - return ILLEGAL_DATA_ADDRESS; // return exception code - } - // if all ok - return no errors - return NO_ERRORS; - } - // if address isnt from this array return error - else - { - MB_DEBUG_PRINT("[MB] Illegal Data Address"); - return ILLEGAL_DATA_ADDRESS; // return exception code - } + // if address from this array + if(Addr >= R_ARR_ADDR) + { + // if quantity too big return error + if ((Addr - R_ARR_ADDR) + Qnt > R_ARR_NUMB) + { + MB_DEBUG_PRINT("[MB] Illegal Data Address"); + return ILLEGAL_DATA_ADDRESS; // return exception code + } + // if all ok - return no errors + return NO_ERRORS; + } + // if address isnt from this array return error + else + { + MB_DEBUG_PRINT("[MB] Illegal Data Address"); + return ILLEGAL_DATA_ADDRESS; // return exception code + } } /** - * @brief Define Address Origin for Input/Holding Registers - * @param pRegs - указатель на указатель регистров. - * @param Addr - адрес начального регистра. - * @param Qnt - количество запрашиваемых регистров. - * @param WriteFlag - флаг регистр нужны для чтения или записи. - * @return ExceptionCode - Код исключения если есть, и NO_ERRORS если нет. - * - * @details Определение адреса начального регистра. - * @note WriteFlag пока не используется. - */ + * @brief Define Address Origin for Input/Holding Registers + * @param pRegs - указатель на указатель регистров. + * @param Addr - адрес начального регистра. + * @param Qnt - количество запрашиваемых регистров. + * @param WriteFlag - флаг регистр нужны для чтения или записи. + * @return ExceptionCode - Код исключения если есть, и NO_ERRORS если нет. + * + * @details Определение адреса начального регистра. + * @note WriteFlag пока не используется. + */ MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, uint16_t Qnt, uint8_t RegisterType) -{ - /* check quantity error */ - if (Qnt > 125) - { - MB_DEBUG_PRINT("[MB] Illegal Data Value"); - return ILLEGAL_DATA_VALUE; // return exception code - } - - if(RegisterType == RegisterType_Holding) - { - // Default holding registers - if(MB_Check_Address_For_Arr(Addr, Qnt, R_HOLDING_ADDR, R_HOLDING_QNT) == NO_ERRORS) - { - *pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr); // указатель на выбранный по Addr регистр - } - // if address doesnt match any array - return illegal data address response - else - { - MB_DEBUG_PRINT("[MB] Illegal Data Address"); - return ILLEGAL_DATA_ADDRESS; - } - } - else if(RegisterType == RegisterType_Input) - { - // Default input registers - if(MB_Check_Address_For_Arr(Addr, Qnt, R_INPUT_ADDR, R_INPUT_QNT) == NO_ERRORS) - { - *pRegs = MB_Set_Register_Ptr(&MB_DATA.InRegs, Addr); // указатель на выбранный по Addr регистр - } - // if address doesnt match any array - return illegal data address response - else - { - MB_DEBUG_PRINT("[MB] Illegal Data Address"); - return ILLEGAL_DATA_ADDRESS; - } - } - else - { - MB_DEBUG_PRINT("[MB] Illegal Function"); - return ILLEGAL_FUNCTION; - } - // if found requeried array return no err - return NO_ERRORS; // return no errors +{ + /* check quantity error */ + if (Qnt > 125) + { + MB_DEBUG_PRINT("[MB] Illegal Data Value"); + return ILLEGAL_DATA_VALUE; // return exception code + } + + if(RegisterType == RegisterType_Holding) + { + // Default holding registers + if(MB_Check_Address_For_Arr(Addr, Qnt, R_HOLDING_ADDR, R_HOLDING_QNT) == NO_ERRORS) + { + *pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr); // указатель на выбранный по Addr регистр + } + // if address doesnt match any array - return illegal data address response + else + { + MB_DEBUG_PRINT("[MB] Illegal Data Address"); + return ILLEGAL_DATA_ADDRESS; + } + } + else if(RegisterType == RegisterType_Input) + { + // Default input registers + if(MB_Check_Address_For_Arr(Addr, Qnt, R_INPUT_ADDR, R_INPUT_QNT) == NO_ERRORS) + { + *pRegs = MB_Set_Register_Ptr(&MB_DATA.InRegs, Addr); // указатель на выбранный по Addr регистр + } + // if address doesnt match any array - return illegal data address response + else + { + MB_DEBUG_PRINT("[MB] Illegal Data Address"); + return ILLEGAL_DATA_ADDRESS; + } + } + else + { + MB_DEBUG_PRINT("[MB] Illegal Function"); + return ILLEGAL_FUNCTION; + } + // if found requeried array return no err + return NO_ERRORS; // return no errors } /** - * @brief Define Address Origin for coils - * @param pCoils - указатель на указатель коилов. - * @param Addr - адресс начального коила. - * @param Qnt - количество запрашиваемых коилов. - * @param start_shift - указатель на переменную содержащую сдвиг внутри регистра для начального коила. - * @param WriteFlag - флаг коилы нужны для чтения или записи. - * @return ExceptionCode - Код исключения если есть, и NO_ERRORS если нет. - * - * @details Определение адреса начального регистра запрашиваемых коилов. - * @note WriteFlag используется для определния регистров GPIO: ODR или IDR. - */ + * @brief Define Address Origin for coils + * @param pCoils - указатель на указатель коилов. + * @param Addr - адресс начального коила. + * @param Qnt - количество запрашиваемых коилов. + * @param start_shift - указатель на переменную содержащую сдвиг внутри регистра для начального коила. + * @param WriteFlag - флаг коилы нужны для чтения или записи. + * @return ExceptionCode - Код исключения если есть, и NO_ERRORS если нет. + * + * @details Определение адреса начального регистра запрашиваемых коилов. + * @note WriteFlag используется для определния регистров GPIO: ODR или IDR. + */ MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint16_t Qnt, uint16_t *start_shift, uint8_t WriteFlag) -{ - /* check quantity error */ - if (Qnt > 2000) - { - MB_DEBUG_PRINT("[MB] Illegal Data Value"); - return ILLEGAL_DATA_VALUE; // return exception code - } - - // Default coils - if(MB_Check_Address_For_Arr(Addr, Qnt, C_CONTROL_ADDR, C_CONTROL_QNT) == NO_ERRORS) - { - *pCoils = MB_Set_Coil_Reg_Ptr(&MB_DATA.Coils, Addr); // указатель на выбранный по Addr массив коилов - } - // if address doesnt match any array - return illegal data address response - else - { - MB_DEBUG_PRINT("[MB] Illegal Data Address"); - return ILLEGAL_DATA_ADDRESS; - } - - *start_shift = Addr % 16; // set shift to requested coil - // if found requeried array return no err - return NO_ERRORS; // return no errors +{ + /* check quantity error */ + if (Qnt > 2000) + { + MB_DEBUG_PRINT("[MB] Illegal Data Value"); + return ILLEGAL_DATA_VALUE; // return exception code + } + + // Default coils + if(MB_Check_Address_For_Arr(Addr, Qnt, C_CONTROL_ADDR, C_CONTROL_QNT) == NO_ERRORS) + { + *pCoils = MB_Set_Coil_Reg_Ptr(&MB_DATA.Coils, Addr); // указатель на выбранный по Addr массив коилов + } + // if address doesnt match any array - return illegal data address response + else + { + MB_DEBUG_PRINT("[MB] Illegal Data Address"); + return ILLEGAL_DATA_ADDRESS; + } + + *start_shift = Addr % 16; // set shift to requested coil + // if found requeried array return no err + return NO_ERRORS; // return no errors } /** - * @brief Proccess command Read Coils (01 - 0x01). - * @param modbus_msg - указатель на структуру собщения modbus. - * @return fMessageHandled - статус о результате обработки комманды. - * @details Обработка команды Read Coils. - */ + * @brief Proccess command Read Coils (01 - 0x01). + * @param modbus_msg - указатель на структуру собщения modbus. + * @return fMessageHandled - статус о результате обработки комманды. + * @details Обработка команды Read Coils. + */ uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg) { - //---------CHECK FOR ERRORS---------- - uint16_t *coils; - uint16_t start_shift = 0; // shift in coils register - - modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 0); - if(modbus_msg->Except_Code != NO_ERRORS) - return 0; - - //-----------READING COIL------------ - // setup output message data size - modbus_msg->ByteCnt = Divide_Up(modbus_msg->Qnt, 8); - // create mask for coils - uint16_t mask_for_coils = 0; // mask for coils that've been chosen - uint16_t setted_coils = 0; // value of setted coils - uint16_t temp_reg = 0; // temp register for saving coils that hasnt been chosen - uint16_t coil_cnt = 0; // counter for processed coils + //---------CHECK FOR ERRORS---------- + uint16_t *coils; + uint16_t start_shift = 0; // shift in coils register + + modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 0); + if(modbus_msg->Except_Code != NO_ERRORS) + return 0; + + //-----------READING COIL------------ + // setup output message data size + modbus_msg->ByteCnt = Divide_Up(modbus_msg->Qnt, 8); + // create mask for coils + uint16_t mask_for_coils = 0; // mask for coils that've been chosen + uint16_t setted_coils = 0; // value of setted coils + uint16_t temp_reg = 0; // temp register for saving coils that hasnt been chosen + uint16_t coil_cnt = 0; // counter for processed coils - // cycle until all registers with requered coils would be processed - int shift = start_shift; // set shift to first coil in first register - int ind = 0; // index for coils registers and data - for(; ind <= Divide_Up(start_shift + modbus_msg->Qnt, 16); ind++) - { - //----SET MASK FOR COILS REGISTER---- - mask_for_coils = 0; - for(; shift < 0x10; shift++) - { - mask_for_coils |= 1<<(shift); // choose certain coil - if(++coil_cnt >= modbus_msg->Qnt) - break; - } - shift = 0; // set shift to zero for the next step - - //-----------READ COILS-------------- - modbus_msg->DATA[ind] = (*(coils+ind)&mask_for_coils) >> start_shift; - if(ind > 0) - modbus_msg->DATA[ind-1] |= ((*(coils+ind)&mask_for_coils) << 16) >> start_shift; - - } - // т.к. DATA 16-битная, для 8-битной передачи, надо поменять местами верхний и нижний байты - for(; ind >= 0; --ind) - modbus_msg->DATA[ind] = ByteSwap16(modbus_msg->DATA[ind]); - - return 1; + // cycle until all registers with requered coils would be processed + int shift = start_shift; // set shift to first coil in first register + int ind = 0; // index for coils registers and data + for(; ind <= Divide_Up(start_shift + modbus_msg->Qnt, 16); ind++) + { + //----SET MASK FOR COILS REGISTER---- + mask_for_coils = 0; + for(; shift < 0x10; shift++) + { + mask_for_coils |= 1<<(shift); // choose certain coil + if(++coil_cnt >= modbus_msg->Qnt) + break; + } + shift = 0; // set shift to zero for the next step + + //-----------READ COILS-------------- + modbus_msg->DWDATA[ind] = (*(coils+ind)&mask_for_coils) >> start_shift; + if(ind > 0) + modbus_msg->DWDATA[ind-1] |= ((*(coils+ind)&mask_for_coils) << 16) >> start_shift; + + } + // т.к. DWDATA 16-битная, для 8-битной передачи, надо поменять местами верхний и нижний байты + for(; ind >= 0; --ind) + modbus_msg->DWDATA[ind] = ByteSwap16(modbus_msg->DWDATA[ind]); + + return 1; } /** - * @brief Proccess command Read Holding Registers (03 - 0x03). - * @param modbus_msg - указатель на структуру собщения modbus. - * @return fMessageHandled - статус о результате обработки комманды. - * @details Обработка команды Read Holding Registers. - */ + * @brief Proccess command Read Holding Registers (03 - 0x03). + * @param modbus_msg - указатель на структуру собщения modbus. + * @return fMessageHandled - статус о результате обработки комманды. + * @details Обработка команды Read Holding Registers. + */ uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg) { - //---------CHECK FOR ERRORS---------- - // get origin address for data - uint16_t *pHoldRegs; - modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров - if(modbus_msg->Except_Code != NO_ERRORS) - return 0; - + //---------CHECK FOR ERRORS---------- + // get origin address for data + uint16_t *pHoldRegs; + modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров + if(modbus_msg->Except_Code != NO_ERRORS) + return 0; + - //-----------READING REGS------------ - // setup output message data size - modbus_msg->ByteCnt = modbus_msg->Qnt*2; // *2 because we transmit 8 bits, not 16 bits - // read data - int i; - for (i = 0; iQnt; i++) - { - modbus_msg->DATA[i] = *(pHoldRegs++); - } - return 1; + //-----------READING REGS------------ + // setup output message data size + modbus_msg->ByteCnt = modbus_msg->Qnt*2; // *2 because we transmit 8 bits, not 16 bits + // read data + int i; + for (i = 0; iQnt; i++) + { + modbus_msg->DWDATA[i] = *(pHoldRegs++); + } + return 1; } /** - * @brief Proccess command Read Input Registers (04 - 0x04). - * @param modbus_msg - указатель на структуру собщения modbus. - * @return fMessageHandled - статус о результате обработки комманды. - * @details Обработка команды Read Input Registers. - */ + * @brief Proccess command Read Input Registers (04 - 0x04). + * @param modbus_msg - указатель на структуру собщения modbus. + * @return fMessageHandled - статус о результате обработки комманды. + * @details Обработка команды Read Input Registers. + */ uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg) { - //---------CHECK FOR ERRORS---------- - // get origin address for data - uint16_t *pInRegs; - modbus_msg->Except_Code = MB_DefineRegistersAddress(&pInRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Input); // определение адреса регистров - if(modbus_msg->Except_Code != NO_ERRORS) - return 0; - + //---------CHECK FOR ERRORS---------- + // get origin address for data + uint16_t *pInRegs; + modbus_msg->Except_Code = MB_DefineRegistersAddress(&pInRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Input); // определение адреса регистров + if(modbus_msg->Except_Code != NO_ERRORS) + return 0; + - //-----------READING REGS------------ - // setup output message data size - modbus_msg->ByteCnt = modbus_msg->Qnt*2; // *2 because we transmit 8 bits, not 16 bits - // read data - int i; - for (i = 0; iQnt; i++) - { + //-----------READING REGS------------ + // setup output message data size + modbus_msg->ByteCnt = modbus_msg->Qnt*2; // *2 because we transmit 8 bits, not 16 bits + // read data + int i; + for (i = 0; iQnt; i++) + { if(*((int16_t *)pInRegs) > 0) - modbus_msg->DATA[i] = (*pInRegs++); + modbus_msg->DWDATA[i] = (*pInRegs++); else - modbus_msg->DATA[i] = (*pInRegs++); - } - return 1; + modbus_msg->DWDATA[i] = (*pInRegs++); + } + return 1; } /** - * @brief Proccess command Write Single Coils (05 - 0x05). - * @param modbus_msg - указатель на структуру собщения modbus. - * @return fMessageHandled - статус о результате обработки комманды. - * @details Обработка команды Write Single Coils. - */ + * @brief Proccess command Write Single Coils (05 - 0x05). + * @param modbus_msg - указатель на структуру собщения modbus. + * @return fMessageHandled - статус о результате обработки комманды. + * @details Обработка команды Write Single Coils. + */ uint8_t MB_Write_Single_Coil(RS_MsgTypeDef *modbus_msg) { - //---------CHECK FOR ERRORS---------- - if ((modbus_msg->Qnt != 0x0000) && (modbus_msg->Qnt != 0xFF00)) - { - modbus_msg->Except_Code = ILLEGAL_DATA_VALUE; - return 0; - } - // define position of coil - uint16_t *coils; - uint16_t start_shift = 0; // shift in coils register - modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, 0, &start_shift, 1); - if(modbus_msg->Except_Code != NO_ERRORS) - return 0; - + //---------CHECK FOR ERRORS---------- + if ((modbus_msg->Qnt != 0x0000) && (modbus_msg->Qnt != 0xFF00)) + { + modbus_msg->Except_Code = ILLEGAL_DATA_VALUE; + return 0; + } + // define position of coil + uint16_t *coils; + uint16_t start_shift = 0; // shift in coils register + modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, 0, &start_shift, 1); + if(modbus_msg->Except_Code != NO_ERRORS) + return 0; + - //----------WRITTING COIL------------ - if(modbus_msg->Qnt == 0xFF00) - *(coils) |= 1<Qnt == 0xFF00) + *(coils) |= 1<Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, 1, RegisterType_Holding); // определение адреса регистров - if(modbus_msg->Except_Code != NO_ERRORS) - return 0; - - //-----------WRITTING REG------------ - *(pHoldRegs) = modbus_msg->Qnt; - return 1; +{ + // get origin address for data + uint16_t *pHoldRegs; + modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, 1, RegisterType_Holding); // определение адреса регистров + if(modbus_msg->Except_Code != NO_ERRORS) + return 0; + + //-----------WRITTING REG------------ + *(pHoldRegs) = modbus_msg->Qnt; + return 1; } /** - * @brief Proccess command Write Multiple Coils (15 - 0x0F). - * @param modbus_msg - указатель на структуру собщения modbus. - * @return fMessageHandled - статус о результате обработки комманды. - * @details Обработка команды Write Multiple Coils. - */ + * @brief Proccess command Write Multiple Coils (15 - 0x0F). + * @param modbus_msg - указатель на структуру собщения modbus. + * @return fMessageHandled - статус о результате обработки комманды. + * @details Обработка команды Write Multiple Coils. + */ uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg) { - //---------CHECK FOR ERRORS---------- - if (modbus_msg->ByteCnt != Divide_Up(modbus_msg->Qnt, 8)) - { // if quantity too large OR if quantity and bytes count arent match - modbus_msg->Except_Code = ILLEGAL_DATA_VALUE; - return 0; - } - // define position of coil - uint16_t *coils; // pointer to coils - uint16_t start_shift = 0; // shift in coils register - modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 1); - if(modbus_msg->Except_Code != NO_ERRORS) - return 0; - - //----------WRITTING COILS----------- - // create mask for coils - uint16_t mask_for_coils = 0; // mask for coils that've been chosen - uint32_t setted_coils = 0; // value of setted coils - uint16_t temp_reg = 0; // temp register for saving coils that hasnt been chosen - uint16_t coil_cnt = 0; // counter for processed coils + //---------CHECK FOR ERRORS---------- + if (modbus_msg->ByteCnt != Divide_Up(modbus_msg->Qnt, 8)) + { // if quantity too large OR if quantity and bytes count arent match + modbus_msg->Except_Code = ILLEGAL_DATA_VALUE; + return 0; + } + // define position of coil + uint16_t *coils; // pointer to coils + uint16_t start_shift = 0; // shift in coils register + modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 1); + if(modbus_msg->Except_Code != NO_ERRORS) + return 0; + + //----------WRITTING COILS----------- + // create mask for coils + uint16_t mask_for_coils = 0; // mask for coils that've been chosen + uint32_t setted_coils = 0; // value of setted coils + uint16_t temp_reg = 0; // temp register for saving coils that hasnt been chosen + uint16_t coil_cnt = 0; // counter for processed coils - // cycle until all registers with requered coils would be processed - int shift = start_shift; // set shift to first coil in first register - for(int ind = 0; ind <= Divide_Up(start_shift + modbus_msg->Qnt, 16); ind++) - { - //----SET MASK FOR COILS REGISTER---- - mask_for_coils = 0; - for(; shift < 0x10; shift++) - { - mask_for_coils |= 1<<(shift); // choose certain coil - if(++coil_cnt >= modbus_msg->Qnt) - break; - } - shift = 0; // set shift to zero for the next step - - - - //-----------WRITE COILS------------- - // get current coils - temp_reg = *(coils+ind); - // set coils - setted_coils = ByteSwap16(modbus_msg->DATA[ind]) << start_shift; - if(ind > 0) - { - setted_coils |= ((ByteSwap16(modbus_msg->DATA[ind-1]) << start_shift) >> 16); - } - // write coils - - *(coils+ind) = setted_coils & mask_for_coils; - // restore untouched coils - *(coils+ind) |= temp_reg&(~mask_for_coils); - - - if(coil_cnt >= modbus_msg->Qnt) // if all coils written - break cycle - break; // *kind of unnecessary - } - - return 1; + // cycle until all registers with requered coils would be processed + int shift = start_shift; // set shift to first coil in first register + for(int ind = 0; ind <= Divide_Up(start_shift + modbus_msg->Qnt, 16); ind++) + { + //----SET MASK FOR COILS REGISTER---- + mask_for_coils = 0; + for(; shift < 0x10; shift++) + { + mask_for_coils |= 1<<(shift); // choose certain coil + if(++coil_cnt >= modbus_msg->Qnt) + break; + } + shift = 0; // set shift to zero for the next step + + + + //-----------WRITE COILS------------- + // get current coils + temp_reg = *(coils+ind); + // set coils + setted_coils = ByteSwap16(modbus_msg->DWDATA[ind]) << start_shift; + if(ind > 0) + { + setted_coils |= ((ByteSwap16(modbus_msg->DWDATA[ind-1]) << start_shift) >> 16); + } + // write coils + + *(coils+ind) = setted_coils & mask_for_coils; + // restore untouched coils + *(coils+ind) |= temp_reg&(~mask_for_coils); + + + if(coil_cnt >= modbus_msg->Qnt) // if all coils written - break cycle + break; // *kind of unnecessary + } + + return 1; } /** - * @brief Proccess command Write Multiple Registers (16 - 0x10). - * @param modbus_msg - указатель на структуру собщения modbus. - * @return fMessageHandled - статус о результате обработки комманды. - * @details Обработка команды Write Multiple Registers. - */ + * @brief Proccess command Write Multiple Registers (16 - 0x10). + * @param modbus_msg - указатель на структуру собщения modbus. + * @return fMessageHandled - статус о результате обработки комманды. + * @details Обработка команды Write Multiple Registers. + */ uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg) { - //---------CHECK FOR ERRORS---------- - if (modbus_msg->Qnt*2 != modbus_msg->ByteCnt) - { // if quantity and bytes count arent match - modbus_msg->Except_Code = ILLEGAL_DATA_VALUE; - return 0; - } - // get origin address for data - uint16_t *pHoldRegs; - modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров - if(modbus_msg->Except_Code != NO_ERRORS) - return 0; - - //-----------WRITTING REGS----------- - for (int i = 0; iQnt; i++) - { - *(pHoldRegs++) = modbus_msg->DATA[i]; - } - return 1; + //---------CHECK FOR ERRORS---------- + if (modbus_msg->Qnt*2 != modbus_msg->ByteCnt) + { // if quantity and bytes count arent match + modbus_msg->Except_Code = ILLEGAL_DATA_VALUE; + return 0; + } + // get origin address for data + uint16_t *pHoldRegs; + modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров + if(modbus_msg->Except_Code != NO_ERRORS) + return 0; + + //-----------WRITTING REGS----------- + for (int i = 0; iQnt; i++) + { + *(pHoldRegs++) = modbus_msg->DWDATA[i]; + } + return 1; } void MB_WriteObjectToMessage(char *mbdata, unsigned *ind, MB_DeviceObjectTypeDef *obj) @@ -566,14 +573,14 @@ void MB_WriteObjectToMessage(char *mbdata, unsigned *ind, MB_DeviceObjectTypeDef } } /** - * @brief Proccess command Read Device Identification (43/14 - 0x2B/0E). - * @param modbus_msg - указатель на структуру собщения modbus. - * @return fMessageHandled - статус о результате обработки комманды. - * @details Обработка команды Write Single Register. - */ + * @brief Proccess command Read Device Identification (43/14 - 0x2B/0E). + * @param modbus_msg - указатель на структуру собщения modbus. + * @return fMessageHandled - статус о результате обработки комманды. + * @details Обработка команды Write Single Register. + */ uint8_t MB_Read_Device_Identification(RS_MsgTypeDef *modbus_msg) { - char *mbdata = (char *)modbus_msg->DATA; + char *mbdata = (char *)modbus_msg->DWDATA; unsigned ind = 0; switch(modbus_msg->DevId.ReadDevId) { @@ -607,149 +614,149 @@ uint8_t MB_Read_Device_Identification(RS_MsgTypeDef *modbus_msg) /** - * @brief Respond accord to received message. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @return RS_RES - статус о результате ответа на комманду. - * @details Обработка принятой комманды и ответ на неё. - */ + * @brief Respond accord to received message. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @return RS_RES - статус о результате ответа на комманду. + * @details Обработка принятой комманды и ответ на неё. + */ RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) { - RS_StatusTypeDef MB_RES = RS_OK; - hmodbus->f.MessageHandled = 0; - hmodbus->f.EchoResponse = 0; - RS_Reset_TX_Flags(hmodbus); // reset flag for correct transmit - - if(modbus_msg->Func_Code < ERR_VALUES_START)// if no errors after parsing - { - switch (modbus_msg->Func_Code) - { - // Read Coils - case MB_R_COILS: - MB_DEBUG_PRINT("[MB] Read Coils request"); - hmodbus->f.MessageHandled = MB_Read_Coils(hmodbus->pMessagePtr); - break; - - // Read Hodling Registers - case MB_R_HOLD_REGS: - MB_DEBUG_PRINT("[MB] Read Hodling Registers request"); - hmodbus->f.MessageHandled = MB_Read_Hold_Regs(hmodbus->pMessagePtr); - break; - case MB_R_IN_REGS: - MB_DEBUG_PRINT("[MB] Read Input Registers request"); - hmodbus->f.MessageHandled = MB_Read_Input_Regs(hmodbus->pMessagePtr); - break; - - - // Write Single Coils - case MB_W_COIL: - MB_DEBUG_PRINT("[MB] Write Single Coil request"); - hmodbus->f.MessageHandled = MB_Write_Single_Coil(hmodbus->pMessagePtr); - if(hmodbus->f.MessageHandled) - { - hmodbus->f.EchoResponse = 1; - hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes) - } - break; - - case MB_W_HOLD_REG: - MB_DEBUG_PRINT("[MB] Write Single Hodling Register request"); - hmodbus->f.MessageHandled = MB_Write_Single_Reg(hmodbus->pMessagePtr); - if(hmodbus->f.MessageHandled) - { - hmodbus->f.EchoResponse = 1; - hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes) - } - break; - - // Write Multiple Coils - case MB_W_COILS: - MB_DEBUG_PRINT("[MB] Write Multiple Coils request"); - hmodbus->f.MessageHandled = MB_Write_Miltuple_Coils(hmodbus->pMessagePtr); - if(hmodbus->f.MessageHandled) - { - hmodbus->f.EchoResponse = 1; - hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes) - } - break; - - // Write Multiple Registers - case MB_W_HOLD_REGS: - MB_DEBUG_PRINT("[MB] Write Multiple Hodling Registers request"); - hmodbus->f.MessageHandled = MB_Write_Miltuple_Regs(hmodbus->pMessagePtr); - if(hmodbus->f.MessageHandled) - { - hmodbus->f.EchoResponse = 1; - hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes) - } - break; - + RS_StatusTypeDef MB_RES = RS_OK; + hmodbus->f.MessageHandled = 0; + hmodbus->f.EchoResponse = 0; + RS_Reset_TX_Flags(hmodbus); // reset flag for correct transmit + + if(modbus_msg->Func_Code < ERR_VALUES_START)// if no errors after parsing + { + switch (modbus_msg->Func_Code) + { + // Read Coils + case MB_R_COILS: + MB_DEBUG_PRINT("[MB] Read Coils request"); + hmodbus->f.MessageHandled = MB_Read_Coils(hmodbus->pMessagePtr); + break; + + // Read Hodling Registers + case MB_R_HOLD_REGS: + MB_DEBUG_PRINT("[MB] Read Hodling Registers request"); + hmodbus->f.MessageHandled = MB_Read_Hold_Regs(hmodbus->pMessagePtr); + break; + case MB_R_IN_REGS: + MB_DEBUG_PRINT("[MB] Read Input Registers request"); + hmodbus->f.MessageHandled = MB_Read_Input_Regs(hmodbus->pMessagePtr); + break; + + + // Write Single Coils + case MB_W_COIL: + MB_DEBUG_PRINT("[MB] Write Single Coil request"); + hmodbus->f.MessageHandled = MB_Write_Single_Coil(hmodbus->pMessagePtr); + if(hmodbus->f.MessageHandled) + { + hmodbus->f.EchoResponse = 1; + hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes) + } + break; + + case MB_W_HOLD_REG: + MB_DEBUG_PRINT("[MB] Write Single Hodling Register request"); + hmodbus->f.MessageHandled = MB_Write_Single_Reg(hmodbus->pMessagePtr); + if(hmodbus->f.MessageHandled) + { + hmodbus->f.EchoResponse = 1; + hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes) + } + break; + + // Write Multiple Coils + case MB_W_COILS: + MB_DEBUG_PRINT("[MB] Write Multiple Coils request"); + hmodbus->f.MessageHandled = MB_Write_Miltuple_Coils(hmodbus->pMessagePtr); + if(hmodbus->f.MessageHandled) + { + hmodbus->f.EchoResponse = 1; + hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes) + } + break; + + // Write Multiple Registers + case MB_W_HOLD_REGS: + MB_DEBUG_PRINT("[MB] Write Multiple Hodling Registers request"); + hmodbus->f.MessageHandled = MB_Write_Miltuple_Regs(hmodbus->pMessagePtr); + if(hmodbus->f.MessageHandled) + { + hmodbus->f.EchoResponse = 1; + hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes) + } + break; + case MB_R_DEVICE_INFO: - MB_DEBUG_PRINT("[MB] Read Device Information request"); + MB_DEBUG_PRINT("[MB] Read Device Information request"); hmodbus->f.MessageHandled = MB_Read_Device_Identification(hmodbus->pMessagePtr); break; - /* unknown func code */ - default: - MB_DEBUG_PRINT("[MB] Illegal function"); - modbus_msg->Except_Code = ILLEGAL_FUNCTION; /* set exception code: illegal function */ - } - - if(hmodbus->f.MessageHandled == 0) + /* unknown func code */ + default: + MB_DEBUG_PRINT("[MB] Illegal function"); + modbus_msg->Except_Code = ILLEGAL_FUNCTION; /* set exception code: illegal function */ + } + + if(hmodbus->f.MessageHandled == 0) { - MB_DEBUG_PRINT("[MB] Function not handled"); - modbus_msg->Func_Code = static_cast( - static_cast(modbus_msg->Func_Code) + ERR_VALUES_START - ); - MB_ERR_DEBUG_PRINT2_HEX("[MB] Function Code:", modbus_msg->Func_Code); - MB_ERR_DEBUG_PRINT2_DEC("[MB] Error Code:", modbus_msg->Except_Code); + MB_DEBUG_PRINT("[MB] Function not handled"); + modbus_msg->Func_Code = static_cast( + static_cast(modbus_msg->Func_Code) + ERR_VALUES_START + ); + MB_ERR_DEBUG_PRINT2_HEX("[MB] Function Code:", modbus_msg->Func_Code); + MB_ERR_DEBUG_PRINT2_DEC("[MB] Error Code:", modbus_msg->Except_Code); } else { - MB_DEBUG_PRINT("[MB] Function handled, responsing..."); + MB_DEBUG_PRINT("[MB] Function handled, responsing..."); } - - - } - - // if we need response - check that transmit isnt busy - if( RS_Is_TX_Busy(hmodbus) ) - RS_Abort(hmodbus, ABORT_TX); // if tx busy - set it free - - // Transmit right there, or sets (fDeferredResponse) to transmit response in main code - MB_RES = RS_Handle_Transmit_Start(hmodbus, modbus_msg); - - hmodbus->RS_STATUS = MB_RES; - return MB_RES; + + + } + + // if we need response - check that transmit isnt busy + if( RS_Is_TX_Busy(hmodbus) ) + RS_Abort(hmodbus, ABORT_TX); // if tx busy - set it free + + // Transmit right there, or sets (fDeferredResponse) to transmit response in main code + MB_RES = RS_Handle_Transmit_Start(hmodbus, modbus_msg); + + hmodbus->RS_STATUS = MB_RES; + return MB_RES; } /** - * @brief Collect message in buffer to transmit it. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @param msg_uart_buff - указатель на буффер UART. - * @return RS_RES - статус о результате заполнения буфера. - * @details Заполнение буффера UART из структуры сообщения. - */ + * @brief Collect message in buffer to transmit it. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @param msg_uart_buff - указатель на буффер UART. + * @return RS_RES - статус о результате заполнения буфера. + * @details Заполнение буффера UART из структуры сообщения. + */ RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) { - int ind = 0; // ind for modbus-uart buffer - - if(hmodbus->f.EchoResponse && hmodbus->f.MessageHandled) // if echo response need - ind = hmodbus->RS_Message_Size; - else - { - //------INFO ABOUT DATA/MESSAGE------ - //-----------[first bytes]----------- - // set ID of message/user - modbus_uart_buff[ind++] = modbus_msg->MbAddr; + int ind = 0; // ind for modbus-uart buffer + + if(hmodbus->f.EchoResponse && hmodbus->f.MessageHandled) // if echo response need + ind = hmodbus->RS_Message_Size; + else + { + //------INFO ABOUT DATA/MESSAGE------ + //-----------[first bytes]----------- + // set ID of message/user + modbus_uart_buff[ind++] = modbus_msg->MbAddr; - // set dat or err response - modbus_uart_buff[ind++] = modbus_msg->Func_Code; + // set dat or err response + modbus_uart_buff[ind++] = modbus_msg->Func_Code; - if (modbus_msg->Func_Code < ERR_VALUES_START) // if no error occur - { + if (modbus_msg->Func_Code < ERR_VALUES_START) // if no error occur + { // fill modbus header if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // devide identification header { @@ -762,16 +769,16 @@ RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mo if (modbus_msg->ByteCnt > DATA_SIZE*2) // if ByteCnt less than DATA_SIZE { - MB_DEBUG_PRINT("[MB] Response is invalid (ByteCnt not match DataSize)"); + MB_DEBUG_PRINT("[MB] Response is invalid (ByteCnt not match DataSize)"); return RS_COLLECT_MSG_ERR; } //---------------DATA---------------- //-----------[data bytes]------------ - uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->DATA; + uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->DWDATA; for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data - { // set data + { // set data modbus_uart_buff[ind++] = *tmp_data_addr; tmp_data_addr++; } @@ -782,20 +789,20 @@ RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mo // set size of received data if (modbus_msg->ByteCnt <= DATA_SIZE*2) // if ByteCnt less than DATA_SIZE modbus_uart_buff[ind++] = modbus_msg->ByteCnt; - else // otherwise return data_size err + else // otherwise return data_size err { - MB_DEBUG_PRINT("[MB] Response is invalid (ByteCnt not match DataSize)"); + MB_DEBUG_PRINT("[MB] Response is invalid (ByteCnt not match DataSize)"); return RS_COLLECT_MSG_ERR; } //---------------DATA---------------- //-----------[data bytes]------------ - uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA; + uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DWDATA; for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data - { // set data - if (i%2 == 0) // HI byte + { // set data + if (i%2 == 0) // HI byte modbus_uart_buff[ind++] = (*tmp_data_addr)>>8; - else // LO byte + else // LO byte { modbus_uart_buff[ind++] = *tmp_data_addr; tmp_data_addr++; @@ -804,48 +811,48 @@ RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mo } - } - else // if some error occur - { // send expection code - modbus_uart_buff[ind++] = modbus_msg->Except_Code; - } - } - //---------------CRC---------------- - //---------[last 16 bytes]---------- - // calc crc of received data - uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); - // write crc to message structure and modbus-uart buffer - modbus_msg->MB_CRC = CRC_VALUE; - modbus_uart_buff[ind++] = CRC_VALUE; - modbus_uart_buff[ind++] = CRC_VALUE >> 8; - - hmodbus->RS_Message_Size = ind; - - return RS_OK; // returns ok + } + else // if some error occur + { // send expection code + modbus_uart_buff[ind++] = modbus_msg->Except_Code; + } + } + //---------------CRC---------------- + //---------[last 16 bytes]---------- + // calc crc of received data + uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); + // write crc to message structure and modbus-uart buffer + modbus_msg->MB_CRC = CRC_VALUE; + modbus_uart_buff[ind++] = CRC_VALUE; + modbus_uart_buff[ind++] = CRC_VALUE >> 8; + + hmodbus->RS_Message_Size = ind; + + return RS_OK; // returns ok } /** - * @brief Parse message from buffer to process it. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @param msg_uart_buff - указатель на буффер UART. - * @return RS_RES - статус о результате заполнения структуры. - * @details Заполнение структуры сообщения из буффера UART. - */ + * @brief Parse message from buffer to process it. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @param msg_uart_buff - указатель на буффер UART. + * @return RS_RES - статус о результате заполнения структуры. + * @details Заполнение структуры сообщения из буффера UART. + */ RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) { - uint32_t check_empty_buff; - int ind = 0; // ind for modbus-uart buffer - //-----INFO ABOUT DATA/MESSAGE------- - //-----------[first bits]------------ - // get ID of message/user - modbus_msg->MbAddr = modbus_uart_buff[ind++]; - if(modbus_msg->MbAddr != hmodbus->ID) - return RS_SKIP; - - // get func code - modbus_msg->Func_Code = static_cast(modbus_uart_buff[ind++]); - if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // if it device identification request + uint32_t check_empty_buff; + int ind = 0; // ind for modbus-uart buffer + //-----INFO ABOUT DATA/MESSAGE------- + //-----------[first bits]------------ + // get ID of message/user + modbus_msg->MbAddr = modbus_uart_buff[ind++]; + if(modbus_msg->MbAddr != hmodbus->ID) + return RS_SKIP; + + // get func code + modbus_msg->Func_Code = static_cast(modbus_uart_buff[ind++]); + if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // if it device identification request { modbus_msg->DevId.MEI_Type = static_cast(modbus_uart_buff[ind++]); modbus_msg->DevId.ReadDevId = static_cast(modbus_uart_buff[ind++]); @@ -854,111 +861,111 @@ RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modb } else // if its classic modbus request { - // get address from CMD - modbus_msg->Addr = modbus_uart_buff[ind++] << 8; - modbus_msg->Addr |= modbus_uart_buff[ind++]; - - // get address from CMD - modbus_msg->Qnt = modbus_uart_buff[ind++] << 8; - modbus_msg->Qnt |= modbus_uart_buff[ind++]; - } - if(hmodbus->f.RX_Half == 0) // if all message received - { - //---------------DATA---------------- - // (optional) - if (modbus_msg->ByteCnt != 0) - { - ind++; // increment ind for data_size byte - //check that data size is correct - if (modbus_msg->ByteCnt > DATA_SIZE*2) - { - modbus_msg->Func_Code = static_cast( - static_cast(modbus_msg->Func_Code) + ERR_VALUES_START - ); - MB_DEBUG_PRINT("[MB] Request is invalid (ByteCnt not match DataSize)"); - return RS_PARSE_MSG_ERR; - } - 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 - { // set data - if (i%2 == 0) - *tmp_data_addr = ((uint16_t)modbus_uart_buff[ind++] << 8); - else - { - *tmp_data_addr |= modbus_uart_buff[ind++]; - tmp_data_addr++; - } - } - } - - //---------------CRC---------------- - //----------[last 16 bits]---------- - // calc crc of received data - uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); - // get crc of received data - modbus_msg->MB_CRC = modbus_uart_buff[ind++]; - modbus_msg->MB_CRC |= modbus_uart_buff[ind++] << 8; - // compare crc - if (modbus_msg->MB_CRC != CRC_VALUE) + // get address from CMD + modbus_msg->Addr = modbus_uart_buff[ind++] << 8; + modbus_msg->Addr |= modbus_uart_buff[ind++]; + + // get address from CMD + modbus_msg->Qnt = modbus_uart_buff[ind++] << 8; + modbus_msg->Qnt |= modbus_uart_buff[ind++]; + } + if(hmodbus->f.RX_Half == 0) // if all message received + { + //---------------DATA---------------- + // (optional) + if (modbus_msg->ByteCnt != 0) { - MB_DEBUG_PRINT("[MB] Request CRC is invalid"); - MB_ERR_DEBUG_PRINT2_HEX("[MB] Request CRC: ", modbus_msg->MB_CRC); - MB_ERR_DEBUG_PRINT2_HEX("[MB] Calced CRC: ", CRC_VALUE); - modbus_msg->Func_Code = static_cast( - static_cast(modbus_msg->Func_Code) + ERR_VALUES_START - ); + ind++; // increment ind for data_size byte + //check that data size is correct + if (modbus_msg->ByteCnt > DATA_SIZE*2) + { + modbus_msg->Func_Code = static_cast( + static_cast(modbus_msg->Func_Code) + ERR_VALUES_START + ); + MB_DEBUG_PRINT("[MB] Request is invalid (ByteCnt not match DataSize)"); + return RS_PARSE_MSG_ERR; + } + uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DWDATA; + for(int i = 0; i < modbus_msg->ByteCnt; i++) // /2 because we transmit 8 bits, not 16 bits + { // set data + if (i%2 == 0) + *tmp_data_addr = ((uint16_t)modbus_uart_buff[ind++] << 8); + else + { + *tmp_data_addr |= modbus_uart_buff[ind++]; + tmp_data_addr++; + } + } } - // hmodbus->MB_RESPONSE = MB_CRC_ERR; // set func code - error about wrong crc - - // check is buffer empty - check_empty_buff = 0; - for(int i=0; iMB_RESPONSE = MB_EMPTY_MSG; // - } - - return RS_OK; - + + //---------------CRC---------------- + //----------[last 16 bits]---------- + // calc crc of received data + uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); + // get crc of received data + modbus_msg->MB_CRC = modbus_uart_buff[ind++]; + modbus_msg->MB_CRC |= modbus_uart_buff[ind++] << 8; + // compare crc + if (modbus_msg->MB_CRC != CRC_VALUE) + { + MB_DEBUG_PRINT("[MB] Request CRC is invalid"); + MB_ERR_DEBUG_PRINT2_HEX("[MB] Request CRC: ", modbus_msg->MB_CRC); + MB_ERR_DEBUG_PRINT2_HEX("[MB] Calced CRC: ", CRC_VALUE); + modbus_msg->Func_Code = static_cast( + static_cast(modbus_msg->Func_Code) + ERR_VALUES_START + ); + } + // hmodbus->MB_RESPONSE = MB_CRC_ERR; // set func code - error about wrong crc + + // check is buffer empty + check_empty_buff = 0; + for(int i=0; iMB_RESPONSE = MB_EMPTY_MSG; // + } + + return RS_OK; + } /** - * @brief Define size of RX Message that need to be received. - * @param hRS - указатель на хендлер RS. - * @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия. - * @return RS_RES - статус о корректности рассчета кол-ва байт для принятия. - * @details Определение сколько байтов надо принять по протоколу. - */ + * @brief Define size of RX Message that need to be received. + * @param hRS - указатель на хендлер RS. + * @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия. + * @return RS_RES - статус о корректности рассчета кол-ва байт для принятия. + * @details Определение сколько байтов надо принять по протоколу. + */ RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hmodbus, uint32_t *rx_data_size) -{ - RS_StatusTypeDef MB_RES = RS_OK; - - MB_RES = RS_Parse_Message(hmodbus, hmodbus->pMessagePtr, hmodbus->pBufferPtr); - if(MB_RES == RS_SKIP) // if message not for us - return MB_RES; // return - +{ + RS_StatusTypeDef MB_RES = RS_OK; - if ((hmodbus->pMessagePtr->Func_Code & ~ERR_VALUES_START) < 0x0F) - { - hmodbus->pMessagePtr->ByteCnt = 0; - *rx_data_size = 1; + MB_RES = RS_Parse_Message(hmodbus, hmodbus->pMessagePtr, hmodbus->pBufferPtr); + if(MB_RES == RS_SKIP) // if message not for us + return MB_RES; // return + + + if ((hmodbus->pMessagePtr->Func_Code & ~ERR_VALUES_START) < 0x0F) + { + hmodbus->pMessagePtr->ByteCnt = 0; + *rx_data_size = 1; - } - else - { - hmodbus->pMessagePtr->ByteCnt = hmodbus->pBufferPtr[RX_FIRST_PART_SIZE-1]; // get numb of data in command - // +1 because that defines is size, not ind. - *rx_data_size = hmodbus->pMessagePtr->ByteCnt + 2; - } + } + else + { + hmodbus->pMessagePtr->ByteCnt = hmodbus->pBufferPtr[RX_FIRST_PART_SIZE-1]; // get numb of data in command + // +1 because that defines is size, not ind. + *rx_data_size = hmodbus->pMessagePtr->ByteCnt + 2; + } if(hmodbus->pMessagePtr->Func_Code == MB_R_DEVICE_INFO) { - *rx_data_size = 0; + *rx_data_size = 0; } - hmodbus->RS_Message_Size = RX_FIRST_PART_SIZE + *rx_data_size; // size of whole message - return RS_OK; + hmodbus->RS_Message_Size = RX_FIRST_PART_SIZE + *rx_data_size; // size of whole message + return RS_OK; } //-----------------------------FOR USER------------------------------ diff --git a/modbus.h b/modbus.h index 16224a3..0d07f90 100644 --- a/modbus.h +++ b/modbus.h @@ -1,105 +1,99 @@ /** - ************************************************************************** - * @file modbus.h - * @brief Заголовочный файл модуля MODBUS. - * @details Данный файл необходимо подключить в rs_message.h. После подключать - * rs_message.h к основному проекту. - * - * @defgroup MODBUS - * @brief Modbus stuff - * - *************************************************************************/ + ************************************************************************** + * @file modbus.h + * @brief Заголовочный файл модуля MODBUS. + * @details Данный файл необходимо подключить в rs_message.h. После подключать + * rs_message.h к основному проекту. + * + * @defgroup MODBUS + * @brief Modbus stuff + * + *************************************************************************/ #ifndef __MODBUS_H_ #define __MODBUS_H_ -#include "modbus_config.h" -#include "modbus_data.h" -//#include "settings.h" // for modbus settings +#include "modbus/modbus_config.h" +#include "modbus/modbus_data.h" /** - * @addtogroup MODBUS_SETTINGS - * @ingroup MODBUS - * @brief Some defines for modbus - @{ - */ -///////////////////////////////////////////////////////////////////// -//////////////////////////---SETTINGS---///////////////////////////// -// USER SETTINGS FOR MODBUS IN interface_config.h -//////////////////////////---SETTINGS---///////////////////////////// - + * @addtogroup MODBUS_SETTINGS + * @ingroup MODBUS + * @brief Some defines for modbus + @{ + */ ///////////////////////////////////////////////////////////////////// /////////////////////---USER MESSAGE DEFINES---////////////////////// //-------------DEFINES FOR STRUCTURE---------------- /* defines for structure of modbus message */ -#define MbAddr_SIZE 1 ///< size of (MbAddr) -#define Func_Code_SIZE 1 ///< size of (Func_Code) -#define Addr_SIZE 2 ///< size of (Addr) -#define Qnt_SIZE 2 ///< size of (Qnt) -#define ByteCnt_SIZE 1 ///< size of (ByteCnt) -#define DATA_SIZE 125 ///< maximum number of data: DWORD (NOT MESSAGE SIZE) -#define CRC_SIZE 2 ///< size of (MB_CRC) in bytes +#define MbAddr_SIZE 1 ///< size of (MbAddr) +#define Func_Code_SIZE 1 ///< size of (Func_Code) +#define Addr_SIZE 2 ///< size of (Addr) +#define Qnt_SIZE 2 ///< size of (Qnt) +#define ByteCnt_SIZE 1 ///< size of (ByteCnt) +#define DATA_SIZE 125 ///< maximum number of data: DWORD (NOT MESSAGE SIZE) +#define CRC_SIZE 2 ///< size of (MB_CRC) in bytes /** @brief Size of whole message */ -#define INFO_SIZE_MAX (MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE+ByteCnt_SIZE) +#define INFO_SIZE_MAX (MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE+ByteCnt_SIZE) /** @brief Size of first part of message that will be received first receive info part of message, than defines size of rest message*/ -#define RX_FIRST_PART_SIZE INFO_SIZE_MAX +#define RX_FIRST_PART_SIZE INFO_SIZE_MAX /** @brief Size of buffer: max size of whole message */ -#define MSG_SIZE_MAX (INFO_SIZE_MAX + DATA_SIZE*2 + CRC_SIZE) // max possible size of message +#define MSG_SIZE_MAX (INFO_SIZE_MAX + DATA_SIZE*2 + CRC_SIZE) // max possible size of message /** @brief Structure for modbus exception codes */ typedef enum //MB_ExceptionTypeDef { - // reading - NO_ERRORS = 0x00, ///< no errors - ILLEGAL_FUNCTION = 0x01, ///< Принятый код функции не может быть обработан - ILLEGAL_DATA_ADDRESS = 0x02, ///< Адрес данных, указанный в запросе, недоступен - ILLEGAL_DATA_VALUE = 0x03, ///< Значение, содержащееся в поле данных запроса, является недопустимой величиной - SLAVE_DEVICE_FAILURE = 0x04, ///< Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие -// ACKNOWLEDGE = 0x05, ///< idk -// SLAVE_DEVICE_BUSY = 0x06, ///< idk -// MEMORY_PARITY_ERROR = 0x08, ///< idk + // reading + NO_ERRORS = 0x00, ///< no errors + ILLEGAL_FUNCTION = 0x01, ///< Принятый код функции не может быть обработан + ILLEGAL_DATA_ADDRESS = 0x02, ///< Адрес данных, указанный в запросе, недоступен + ILLEGAL_DATA_VALUE = 0x03, ///< Значение, содержащееся в поле данных запроса, является недопустимой величиной + SLAVE_DEVICE_FAILURE = 0x04, ///< Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие +// ACKNOWLEDGE = 0x05, ///< idk +// SLAVE_DEVICE_BUSY = 0x06, ///< idk +// MEMORY_PARITY_ERROR = 0x08, ///< idk }MB_ExceptionTypeDef; -#define ERR_VALUES_START 0x80U ///< from this value starts error func codes +#define ERR_VALUES_START 0x80U ///< from this value starts error func codes /** @brief Structure for modbus func codes */ typedef enum //MB_FunctonTypeDef { /* COMMANDS */ - // reading - MB_R_COILS = 0x01, ///< Чтение битовых ячеек - MB_R_DISC_IN = 0x02, ///< Чтение дискретных входов + // reading + MB_R_COILS = 0x01, ///< Чтение битовых ячеек + MB_R_DISC_IN = 0x02, ///< Чтение дискретных входов #ifndef MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS - MB_R_HOLD_REGS = 0x03, ///< Чтение входных регистров - MB_R_IN_REGS = 0x04, ///< Чтение регистров хранения + MB_R_HOLD_REGS = 0x03, ///< Чтение входных регистров + MB_R_IN_REGS = 0x04, ///< Чтение регистров хранения #else - MB_R_HOLD_REGS = 0x04, ///< Чтение входных регистров - MB_R_IN_REGS = 0x03, ///< Чтение регистров хранения + MB_R_HOLD_REGS = 0x04, ///< Чтение входных регистров + MB_R_IN_REGS = 0x03, ///< Чтение регистров хранения #endif - - // writting - MB_W_COIL = 0x05, ///< Запись битовой ячейки - MB_W_HOLD_REG = 0x06, ///< Запись одиночного регистра - MB_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек - MB_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров - MB_R_DEVICE_INFO = 0x2B, ///< Чтения информации об устройстве + // writting + MB_W_COIL = 0x05, ///< Запись битовой ячейки + MB_W_HOLD_REG = 0x06, ///< Запись одиночного регистра + MB_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек + MB_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров + + MB_R_DEVICE_INFO = 0x2B, ///< Чтения информации об устройстве /* ERRORS */ - // error reading - MB_ERR_R_COILS = MB_R_COILS + ERR_VALUES_START, ///< Ошибка чтения битовых ячеек - MB_ERR_R_DISC_IN = MB_R_DISC_IN + ERR_VALUES_START, ///< Ошибка чтения дискретных входов - MB_ERR_R_IN_REGS = MB_R_IN_REGS + ERR_VALUES_START, ///< Ошибка чтения регистров хранения - MB_ERR_R_HOLD_REGS = MB_R_HOLD_REGS + ERR_VALUES_START, ///< Ошибка чтения входных регистров - - // error writting - MB_ERR_W_COIL = MB_W_COIL + 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_HOLD_REGS = MB_W_HOLD_REGS + ERR_VALUES_START, ///< Ошибка записи нескольких регистров + // error reading + MB_ERR_R_COILS = MB_R_COILS + ERR_VALUES_START, ///< Ошибка чтения битовых ячеек + MB_ERR_R_DISC_IN = MB_R_DISC_IN + ERR_VALUES_START, ///< Ошибка чтения дискретных входов + MB_ERR_R_IN_REGS = MB_R_IN_REGS + ERR_VALUES_START, ///< Ошибка чтения регистров хранения + MB_ERR_R_HOLD_REGS = MB_R_HOLD_REGS + ERR_VALUES_START, ///< Ошибка чтения входных регистров + + // error writting + MB_ERR_W_COIL = MB_W_COIL + 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_HOLD_REGS = MB_W_HOLD_REGS + ERR_VALUES_START, ///< Ошибка записи нескольких регистров }MB_FunctonTypeDef; /** @brief Structure for MEI func codes */ @@ -123,7 +117,7 @@ typedef enum //MB_FunctonTypeDef /** @brief Structure for decive identification message type */ 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 Conformity; uint8_t MoreFollows; ///< in this library always a zero @@ -132,19 +126,19 @@ typedef struct }MB_DevIdMsgTypeDef; /** @brief Structure for modbus messsage */ -typedef struct // RS_MsgTypeDef +typedef struct // RS_MsgTypeDef { - uint8_t MbAddr; ///< Modbus Slave Address - MB_FunctonTypeDef Func_Code; ///< Modbus Function Code + uint8_t MbAddr; ///< Modbus Slave Address + MB_FunctonTypeDef Func_Code; ///< Modbus Function Code MB_DevIdMsgTypeDef DevId; ///< Read Device Identification Header struct - uint16_t Addr; ///< Modbus Address of data - uint16_t Qnt; ///< Quantity of modbus data - uint8_t ByteCnt; ///< Quantity of bytes of data in message to transmit/receive - - uint16_t DATA[DATA_SIZE]; ///< Modbus Data - MB_ExceptionTypeDef Except_Code; ///< Exception Code for the command - - uint16_t MB_CRC; ///< Modbus CRC + uint16_t Addr; ///< Modbus Address of data + uint16_t Qnt; ///< Quantity of modbus data + uint8_t ByteCnt; ///< Quantity of bytes of data in message to transmit/receive + + uint16_t DWDATA[DATA_SIZE]; ///< Modbus Data (Words) + MB_ExceptionTypeDef Except_Code; ///< Exception Code for the command + + uint16_t MB_CRC; ///< Modbus CRC }RS_MsgTypeDef; //-------------------------------------------------- extern RS_MsgTypeDef MODBUS_MSG; @@ -158,129 +152,129 @@ extern RS_MsgTypeDef MODBUS_MSG; ///////////////////////////////////////////////////////////////////// ////////////////////---MODBUS MESSAGE DEFINES---///////////////////// /** - * @addtogroup MODBUS_MESSAGE_DEFINES - * @ingroup MODBUS - * @brief Some defines for modbus - @{ - */ + * @addtogroup MODBUS_MESSAGE_DEFINES + * @ingroup MODBUS + * @brief Some defines for modbus + @{ + */ /** @brief Structure for coils operation */ typedef enum { - SET_COIL, - RESET_COIL, - TOOGLE_COIL, + SET_COIL, + RESET_COIL, + TOOGLE_COIL, }MB_CoilsOpTypeDef; //-------------------------------------------------- /** - * @brief Macros to set pointer to 16-bit array - * @param _arr_ - массив регистров (16-бит). - */ -#define MB_Set_Arr16_Ptr(_arr_) ((uint16_t*)(&(_arr_))) + * @brief Macros to set pointer to 16-bit array + * @param _arr_ - массив регистров (16-бит). + */ +#define MB_Set_Arr16_Ptr(_arr_) ((uint16_t*)(&(_arr_))) /** - * @brief Macros to set pointer to register - * @param _parr_ - массив регистров. - * @param _addr_ - Номер регистра (его индекс) от начала массива _arr_. - */ -#define MB_Set_Register_Ptr(_parr_, _addr_) ((uint16_t *)(_parr_)+(_addr_)) + * @brief Macros to set pointer to register + * @param _parr_ - массив регистров. + * @param _addr_ - Номер регистра (его индекс) от начала массива _arr_. + */ +#define MB_Set_Register_Ptr(_parr_, _addr_) ((uint16_t *)(_parr_)+(_addr_)) /** - * @brief Macros to set pointer to a certain register that contains certain coil - * @param _parr_ - массив коилов. - * @param _coil_ - Номер коила от начала массива _arr_. - * @note Используется вместе с @ref MB_Set_Coil_Mask - @verbatim Пояснение выражений - (_coil_/16) - get index (address shift) of register that contain certain coil - Visual explanation: 30th coil in coils registers array - xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx - |register[0]----| |register[1]----| - |skip this------| |get this-------| - |shift to 14 bit| - @endverbatim - */ -#define MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ((uint16_t *)(_parr_)+((_coil_)/16)) + * @brief Macros to set pointer to a certain register that contains certain coil + * @param _parr_ - массив коилов. + * @param _coil_ - Номер коила от начала массива _arr_. + * @note Используется вместе с @ref MB_Set_Coil_Mask + @verbatim Пояснение выражений + (_coil_/16) - get index (address shift) of register that contain certain coil + Visual explanation: 30th coil in coils registers array + xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx + |register[0]----| |register[1]----| + |skip this------| |get this-------| + |shift to 14 bit| + @endverbatim + */ +#define MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ((uint16_t *)(_parr_)+((_coil_)/16)) /** - * @brief Macros to set mask to a certain bit in coils register - * @param _coil_ - Номер коила от начала массива _arr_. - * @note Используется вместе с @ref MB_Set_Coil_Reg_Ptr - @verbatim Пояснение выражений - (16*(_coil_/16) - how many coils we need to skip. e.g. (16*30/16) - skip 16 coils from first register - _coil_-(16*(_coil_/16)) - shift to certain coil in certain register - e.g. Coil(30) gets in register[1] (30/16 = 1) coil №14 (30 - (16*30/16) = 30 - 16 = 14) - - Visual explanation: 30th coil in coils registers array - xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx - |register[0]----| |register[1]----| - |skip this------| |get this-------| - |shift to 14 bit| - @endverbatim - */ -#define MB_Set_Coil_Mask(_coil_) (1 << ( _coil_ - (16*((_coil_)/16)) )) - + * @brief Macros to set mask to a certain bit in coils register + * @param _coil_ - Номер коила от начала массива _arr_. + * @note Используется вместе с @ref MB_Set_Coil_Reg_Ptr + @verbatim Пояснение выражений + (16*(_coil_/16) - how many coils we need to skip. e.g. (16*30/16) - skip 16 coils from first register + _coil_-(16*(_coil_/16)) - shift to certain coil in certain register + e.g. Coil(30) gets in register[1] (30/16 = 1) coil №14 (30 - (16*30/16) = 30 - 16 = 14) + + Visual explanation: 30th coil in coils registers array + xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx + |register[0]----| |register[1]----| + |skip this------| |get this-------| + |shift to 14 bit| + @endverbatim + */ +#define MB_Set_Coil_Mask(_coil_) (1 << ( _coil_ - (16*((_coil_)/16)) )) + /** - * @brief Read Coil at its local address. - * @param _parr_ - массив коилов. - * @param _coil_ - Номер коила от начала массива _arr_. - * @return uint16_t - Возвращает запрошенный коил на 0м бите. - * - * @details Позволяет обратиться к коилу по адресу относительно _arr_. - */ -#define MB_Read_Coil_Local(_parr_, _coil_) (( *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) & MB_Set_Coil_Mask(_coil_) ) >> (_coil_)) + * @brief Read Coil at its local address. + * @param _parr_ - массив коилов. + * @param _coil_ - Номер коила от начала массива _arr_. + * @return uint16_t - Возвращает запрошенный коил на 0м бите. + * + * @details Позволяет обратиться к коилу по адресу относительно _arr_. + */ +#define MB_Read_Coil_Local(_parr_, _coil_) (( *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) & MB_Set_Coil_Mask(_coil_) ) >> (_coil_)) /** - * @brief Set Coil at its local address. - * @param _parr_ - указатель на массив коилов. - * @param _coil_ - Номер коила от начала массива _arr_. - * - * @details Позволяет обратиться к коилу по адресу относительно _arr_. - */ -#define MB_Set_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) |= MB_Set_Coil_Mask(_coil_) + * @brief Set Coil at its local address. + * @param _parr_ - указатель на массив коилов. + * @param _coil_ - Номер коила от начала массива _arr_. + * + * @details Позволяет обратиться к коилу по адресу относительно _arr_. + */ +#define MB_Set_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) |= MB_Set_Coil_Mask(_coil_) /** - * @brief Reset Coil at its local address. - * @param _parr_ - указатель на массив коилов. - * @param _coil_ - Номер коила от начала массива _arr_. - * - * @details Позволяет обратиться к коилу по адресу относительно _arr_. - */ -#define MB_Reset_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) &= ~(MB_Set_Coil_Mask(_coil_)) + * @brief Reset Coil at its local address. + * @param _parr_ - указатель на массив коилов. + * @param _coil_ - Номер коила от начала массива _arr_. + * + * @details Позволяет обратиться к коилу по адресу относительно _arr_. + */ +#define MB_Reset_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) &= ~(MB_Set_Coil_Mask(_coil_)) /** - * @brief Set Coil at its local address. - * @param _parr_ - указатель на массив коилов. - * @param _coil_ - Номер коила от начала массива _arr_. - * - * @details Позволяет обратиться к коилу по адресу относительно _arr_. - */ -#define MB_Toogle_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ^= MB_Set_Coil_Mask(_coil_) + * @brief Set Coil at its local address. + * @param _parr_ - указатель на массив коилов. + * @param _coil_ - Номер коила от начала массива _arr_. + * + * @details Позволяет обратиться к коилу по адресу относительно _arr_. + */ +#define MB_Toogle_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ^= MB_Set_Coil_Mask(_coil_) //-------------------------------------------------- //------------------OTHER DEFINES------------------- -#define RegisterType_Holding 0 -#define RegisterType_Input 1 -#define RegisterType_Discrete 2 +#define RegisterType_Holding 0 +#define RegisterType_Input 1 +#define RegisterType_Discrete 2 // create hadnles and settings for uart, tim, rs with _modbus_ name //-------------------------------------------------- #ifndef Divide_Up /** - * @brief Calc dividing including remainder - * @param _val_ - делимое. - * @param _div_ - делитель. - * @details Если результат деления без остатка: он возвращается как есть - Если с остатком - округляется вверх - */ -//#define Divide_Up(_val_, _div_) (((_val_)%(_div_))? (_val_)/(_div_)+1 : (_val_)/_div_) /* через тернарный оператор */ -#define Divide_Up(_val_, _div_) ((_val_ - 1) / _div_) + 1 /* через мат выражение */ + * @brief Calc dividing including remainder + * @param _val_ - делимое. + * @param _div_ - делитель. + * @details Если результат деления без остатка: он возвращается как есть + Если с остатком - округляется вверх + */ +//#define Divide_Up(_val_, _div_) (((_val_)%(_div_))? (_val_)/(_div_)+1 : (_val_)/_div_) /* через тернарный оператор */ +#define Divide_Up(_val_, _div_) ((_val_ - 1) / _div_) + 1 /* через мат выражение */ #endif #ifndef ByteSwap16 /** - * @brief Swap between Little Endian and Big Endian - * @param v - Переменная для свапа. - * @return v (new) - Свапнутая переменная. - * @details Переключения между двумя типами хранения слова: HI-LO байты и LO-HI байты. - */ -#define ByteSwap16(v) (((v&0xFF00) >> (8)) | ((v&0x00FF) << (8))) + * @brief Swap between Little Endian and Big Endian + * @param v - Переменная для свапа. + * @return v (new) - Свапнутая переменная. + * @details Переключения между двумя типами хранения слова: HI-LO байты и LO-HI байты. + */ +#define ByteSwap16(v) (((v&0xFF00) >> (8)) | ((v&0x00FF) << (8))) #endif /** GENERAL_MODBUS_STUFF * @} @@ -292,18 +286,18 @@ typedef enum ///////////////////////////////////////////////////////////////////// /////////////////////////---FUNCTIONS---///////////////////////////// /** - * @addtogroup MODBUS_FUNCTIONS - * @ingroup MODBUS - * @brief Function for controling modbus communication - */ - + * @addtogroup MODBUS_FUNCTIONS + * @ingroup MODBUS + * @brief Function for controling modbus communication + */ + //----------------FUNCTIONS FOR USER---------------- /** - * @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS - * @ingroup MODBUS_FUNCTIONS - * @brief Function for user use - @{ - */ + * @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS + * @ingroup MODBUS_FUNCTIONS + * @brief Function for user use + @{ + */ /* First set up of MODBUS */ void MODBUS_FirstInit(void); /* Set or Reset Coil at its global address */ @@ -314,14 +308,14 @@ uint16_t MB_Read_Coil_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception); /** MODBUS_DATA_ACCESS_FUNCTIONS * @} */ - + //---------PROCESS MODBUS COMMAND FUNCTIONS--------- /** - * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS - * @ingroup MODBUS_FUNCTIONS - * @brief Function process commands - @{ - */ + * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS + * @ingroup MODBUS_FUNCTIONS + * @brief Function process commands + @{ + */ /* Check is address valid for certain array */ MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16_t R_ARR_ADDR, uint16_t R_ARR_NUMB); /* Define Address Origin for Input/Holding Registers */ @@ -334,7 +328,7 @@ uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg); uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg); /* Proccess command Read Input Registers (04 - 0x04) */ uint8_t MB_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); /* Proccess command Write Multiple Coils (15 - 0x0F) */ uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg); @@ -345,9 +339,9 @@ uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg); * @} */ /////////////////////////---FUNCTIONS---///////////////////////////// - - - + + + ///////////////////////////////////////////////////////////////////// /////////////////////////---CALC DEFINES---////////////////////////// @@ -356,7 +350,7 @@ uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg); #ifndef Trace_MB_UART_Enter #define Trace_MB_UART_Enter() #endif //Trace_MB_UART_Enter - + #ifndef Trace_MB_UART_Exit #define Trace_MB_UART_Exit() #endif //Trace_MB_UART_Exit @@ -364,7 +358,7 @@ uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg); #ifndef Trace_MB_TIM_Enter #define Trace_MB_TIM_Enter() #endif //Trace_MB_TIM_Enter - + #ifndef Trace_MB_TIM_Exit #define Trace_MB_TIM_Exit() #endif //Trace_MB_TIM_Exit diff --git a/modbus_config.h b/modbus_config.h index 31ea3b5..49ed1d2 100644 --- a/modbus_config.h +++ b/modbus_config.h @@ -7,8 +7,7 @@ #ifndef _MODBUS_CONFIG_H_ #define _MODBUS_CONFIG_H_ -#define RS_IN_FREERTOS 20 ///< значение - период таска - +#define RS_IN_RTOS 20 ///< значение - период таска // Включить/выключить debug #define RS_DEBUG 1 ///< Отладка приема/передачи UART @@ -16,12 +15,12 @@ #define MODBUS_ERR_DEBUG 1 ///< Отладка ошибок по CAN // MODBUS PARAMS -#define MODBUS_DEVICE_ID 1 ///< девайс текущего устройства -#define MODBUS_TIMEOUT 5000 ///< максимальнйы тайтаут MB в мс +#define MODBUS_DEVICE_ID 1 ///< девайс текущего устройства +#define MODBUS_TIMEOUT 5000 ///< максимальнйы тайтаут MB в мс // PERIPH FUNCTIONS AND HANDLERS #define HUART_TypeDef HardwareSerial -#define rs_huart Serial1 //используемый uart +#define rs_huart Serial2 //используемый uart1` #define MODBUS_SPEED 115200 #define MODBUS_RX_PIN 8 #define MODBUS_TX_PIN 9 diff --git a/modbus_data.h b/modbus_data.h index e2b5158..8688253 100644 --- a/modbus_data.h +++ b/modbus_data.h @@ -29,10 +29,10 @@ При добавлении новых массивов регистров, необходимо их добавить в функцию MB_DefineRegistersAddress - if(MB_Check_Address_For_Arr(Addr, Qnt, R__ADDR, R__QNT) == NO_ERRORS) - { - *pRegs = MB_Set_Register_Ptr(&, Addr); // начало регистров хранения/входных - } + if(MB_Check_Address_For_Arr(Addr, Qnt, R__ADDR, R__QNT) == NO_ERRORS) + { + *pRegs = MB_Set_Register_Ptr(&, Addr); // начало регистров хранения/входных + } @endverbatim * @{ */ @@ -134,8 +134,8 @@ extern MB_DataStructureTypeDef MB_DATA; */ typedef struct { - unsigned length; - char *name; + unsigned length; + const char *name; }MB_DeviceObjectTypeDef; /** * @brief Структура для объектов Modbus diff --git a/rs_message.cpp b/rs_message.cpp index e2614a4..5440407 100644 --- a/rs_message.cpp +++ b/rs_message.cpp @@ -35,7 +35,7 @@ * * @note * - В режиме Arduino loop необходимо вызывать RS_Process() в основном цикле. -* - В режиме FreeRTOS требуется определить макрос RS_IN_FREERTOS, +* - В режиме FreeRTOS требуется определить макрос RS_IN_RTOS, * создать задачу RS_Task и подключить RS_UART_RX_Handler() к ISR UART. * - UART используется через стандартный Arduino Stream API (write, read, available). * @@ -50,7 +50,7 @@ void loop() { RS_Process(&hRS); } * @endverbatim -* Пример использования с FreeRTOS: +* Пример использования с RTOS: * @verbatim RS_HandleTypeDef hRS; RS_MsgTypeDef msg; @@ -65,24 +65,20 @@ void eventSerial() { * @endverbatim **************************************************************************/ -#include "rs_message.h" - -#ifdef RS_IN_FREERTOS -#include -#endif +#include "modbus/rs_message.h" uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer //------------------------------------------------------------------- //-------------------------GENERAL FUNCTIONS------------------------- /** - * @brief Initialize UART and handle RS stucture. - * @param hRS - указатель на хендлер RS. - * @param SerialPort - указатель на структуру с настройками UART. - * @param pRS_BufferPtr - указатель на буффер для приема-передачи по UART. Если он NULL, то поставиться библиотечный буфер. - * @return RS_RES - статус о состоянии RS после инициализации. - * @note Инициализация периферии и структуры для приема-передачи по RS. - */ + * @brief Initialize UART and handle RS stucture. + * @param hRS - указатель на хендлер RS. + * @param SerialPort - указатель на структуру с настройками UART. + * @param pRS_BufferPtr - указатель на буффер для приема-передачи по UART. Если он NULL, то поставиться библиотечный буфер. + * @return RS_RES - статус о состоянии RS после инициализации. + * @note Инициализация периферии и структуры для приема-передачи по RS. + */ RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *SerialPort, uint32_t baudRate, uint8_t *pRS_BufferPtr) { if (!hRS || !SerialPort) { RS_DEBUG_PRINT("[RS] Init error: null handler or port"); @@ -100,9 +96,9 @@ RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *SerialPort, uint3 hRS->f.RX_Half = 0; hRS->lastByteTime = 0; - RS_EnableReceive(); - RS_Set_Busy(hRS); - RS_Set_RX_Flags(hRS); + RS_EnableReceive(); + RS_Set_Busy(hRS); + RS_Set_RX_Flags(hRS); hRS->huart->begin(hRS->baudRate, SERIAL_8N1, hRS->rx_pin, hRS->tx_pin); @@ -111,14 +107,14 @@ RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *SerialPort, uint3 } /** - * @brief Abort RS/UART. - * @param hRS - указатель на хендлер RS. - * @param AbortMode - выбор, что надо отменить. - - ABORT_TX: Отмена передачи по ЮАРТ, с очищением флагов TX, - - ABORT_RX: Отмена приема по ЮАРТ, с очищением флагов RX, - - ABORT_RX_TX: Отмена приема и передачи по ЮАРТ, - - ABORT_RS: Отмена приема-передачи RS, с очищением всей структуры. - * @return RS_RES - статус о состоянии RS после аборта. + * @brief Abort RS/UART. + * @param hRS - указатель на хендлер RS. + * @param AbortMode - выбор, что надо отменить. + - ABORT_TX: Отмена передачи по ЮАРТ, с очищением флагов TX, + - ABORT_RX: Отмена приема по ЮАРТ, с очищением флагов RX, + - ABORT_RX_TX: Отмена приема и передачи по ЮАРТ, + - ABORT_RS: Отмена приема-передачи RS, с очищением всей структуры. + * @return RS_RES - статус о состоянии RS после аборта. * @details В Arduino аппаратный UART (Serial) не отключается физически, * т.к. стандартный API HardwareSerial не даёт прямого доступа * к регистрах UART. RS_Abort лишь очищает внутренние флаги @@ -149,12 +145,12 @@ RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode) { } /** - * @brief Handle for starting transmit. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @return RS_RES - статус о состоянии RS после инициализации передачи. - * @details Определяет отвечать ли на команду или нет. - */ + * @brief Handle for starting transmit. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @return RS_RES - статус о состоянии RS после инициализации передачи. + * @details Определяет отвечать ли на команду или нет. + */ RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) { if (hRS == nullptr || RS_msg == nullptr) { @@ -180,14 +176,14 @@ RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef * hRS->huart->write(hRS->pBufferPtr, hRS->RS_Message_Size); RS_Set_TX_End(hRS); - RS_Set_RX_Flags(hRS); - RS_Set_RX_Flags(hRS); + RS_Set_RX_Flags(hRS); + RS_Set_RX_Flags(hRS); RS_DEBUG_PRINT("[RS] TX finished"); return RS_OK; } -#ifdef RS_IN_FREERTOS +#ifdef RS_IN_RTOS /** * @brief Задача обработки UART приёма (FreeRTOS). @@ -203,7 +199,7 @@ void RS_Task(void *pvParameters) { vTaskDelay(pdMS_TO_TICKS(hRS->taskDelay)); } } -#endif // RS_IN_FREERTOS +#endif // RS_IN_RTOS /** @@ -256,7 +252,7 @@ void RS_Process(RS_HandleTypeDef *hRS) // Если достигнут размер первой части пакета — определяем полный размер if (rx_index == RX_FIRST_PART_SIZE && (hRS->f.RX_Half == 0) && hRS->sRS_RX_Size_Mode == RS_RX_Size_NotConst) { - hRS->f.RX_Half = 1; + hRS->f.RX_Half = 1; uint32_t data_size; RS_DEBUG_PRINT("[RS] Defining size..."); RS_Define_Size_of_RX_Message(hRS, &data_size); @@ -292,39 +288,39 @@ void RS_Process(RS_HandleTypeDef *hRS) //------------------------------------------------------------------- //--------------WEAK PROTOTYPES FOR PROCESSING MESSAGE--------------- /** - * @brief Respond accord to received message. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @return RS_RES - статус о результате ответа на комманду. - * @details Обработка принятой комманды и ответ на неё. - */ + * @brief Respond accord to received message. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @return RS_RES - статус о результате ответа на комманду. + * @details Обработка принятой комманды и ответ на неё. + */ __attribute__((weak)) RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) { return RS_ERR; } /** - * @brief Collect message in buffer to transmit it. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @param msg_uart_buff - указатель на буффер UART. - * @return RS_RES - статус о результате заполнения буфера. - * @details Заполнение буффера UART из структуры сообщения. - */ + * @brief Collect message in buffer to transmit it. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @param msg_uart_buff - указатель на буффер UART. + * @return RS_RES - статус о результате заполнения буфера. + * @details Заполнение буффера UART из структуры сообщения. + */ __attribute__((weak)) RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) { return RS_ERR; } /** - * @brief Parse message from buffer to process it. - * @param hRS - указатель на хендлер RS. - * @param RS_msg - указатель на структуру сообщения. - * @param msg_uart_buff - указатель на буффер UART. - * @return RS_RES - статус о результате заполнения структуры. - * @details Заполнение структуры сообщения из буффера UART. - */ + * @brief Parse message from buffer to process it. + * @param hRS - указатель на хендлер RS. + * @param RS_msg - указатель на структуру сообщения. + * @param msg_uart_buff - указатель на буффер UART. + * @return RS_RES - статус о результате заполнения структуры. + * @details Заполнение структуры сообщения из буффера UART. + */ __attribute__((weak)) RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) { return RS_ERR; } /** - * @brief Define size of RX Message that need to be received. - * @param hRS - указатель на хендлер RS. - * @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия. - * @return RS_RES - статус о корректности рассчета кол-ва байт для принятия. - * @details Определение сколько байтов надо принять по протоколу. - */ + * @brief Define size of RX Message that need to be received. + * @param hRS - указатель на хендлер RS. + * @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия. + * @return RS_RES - статус о корректности рассчета кол-ва байт для принятия. + * @details Определение сколько байтов надо принять по протоколу. + */ __attribute__((weak)) RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *rx_data_size) { return RS_ERR; } diff --git a/rs_message.h b/rs_message.h index 4c2cb0d..b9cfa6e 100644 --- a/rs_message.h +++ b/rs_message.h @@ -4,7 +4,7 @@ * @brief Заголовочный файл для модуля реализации протоколов по RS/UART. ************************************************************************** * @defgroup RS_TOOLS -* @brief Всякое для работы по UART/RS +* @brief Всякое для работы по UART/RS ************************************************************************** @details ************************************************************************** @@ -12,7 +12,7 @@ - Определить структуру сообщения RS_MsgTypeDef и дефайны RX_FIRST_PART_SIZE и MSG_SIZE_MAX. - Подключить этот файл в раздел rs_message.h. - - Определить функции для обработки сообщения: RS_Parse_Message(), + - Определить функции для обработки сообщения: RS_Parse_Message(), RS_Collect_Message(), RS_Response(), RS_Define_Size_of_RX_Message() ************************************************************************** @verbatim @@ -21,7 +21,7 @@ *************************************************************************/ #ifndef __RS_LIB_H_ #define __RS_LIB_H_ -#include "modbus.h" +#include "modbus/modbus.h" ///////////////////////////////////////////////////////////////////// ////////////////////////////---DEFINES---//////////////////////////// @@ -75,99 +75,99 @@ ///////////////////////---STRUCTURES & ENUMS---////////////////////// //------------------ENUMERATIONS-------------------- /** @brief Enums for respond CMD about RS status */ -typedef enum // RS_StatusTypeDef +typedef enum // RS_StatusTypeDef { - /* IN-CODE STATUS (start from 0x01, and goes up)*/ - /*0x01*/ RS_OK = 0x01, - /*0x02*/ RS_ERR, - /*0x03*/ RS_ABORTED, - /*0x04*/ RS_BUSY, - /*0x05*/ RS_SKIP, - - /*0x06*/ RS_COLLECT_MSG_ERR, - /*0x07*/ RS_PARSE_MSG_ERR, - - // reserved values -// /*0x00*/ RS_UNKNOWN_ERR = 0x00, ///< reserved for case, if no one error founded (nothing changed response from zero) + /* IN-CODE STATUS (start from 0x01, and goes up)*/ + /*0x01*/ RS_OK = 0x01, + /*0x02*/ RS_ERR, + /*0x03*/ RS_ABORTED, + /*0x04*/ RS_BUSY, + /*0x05*/ RS_SKIP, + + /*0x06*/ RS_COLLECT_MSG_ERR, + /*0x07*/ RS_PARSE_MSG_ERR, + + // reserved values +// /*0x00*/ RS_UNKNOWN_ERR = 0x00, ///< reserved for case, if no one error founded (nothing changed response from zero) }RS_StatusTypeDef; /** @brief Enums for RS Modes */ -typedef enum // RS_ModeTypeDef +typedef enum // RS_ModeTypeDef { - SLAVE_ALWAYS_WAIT = 0x01, ///< Slave mode with infinity waiting - SLAVE_TIMEOUT_WAIT = 0x02, ///< Slave mode with waiting with timeout -// MASTER = 0x03, ///< Master mode + SLAVE_ALWAYS_WAIT = 0x01, ///< Slave mode with infinity waiting + SLAVE_TIMEOUT_WAIT = 0x02, ///< Slave mode with waiting with timeout +// MASTER = 0x03, ///< Master mode }RS_ModeTypeDef; /** @brief Enums for Abort modes */ -typedef enum // RS_AbortTypeDef +typedef enum // RS_AbortTypeDef { - ABORT_TX = 0x01, ///< Abort transmit - ABORT_RX = 0x02, ///< Abort receive - ABORT_RX_TX = 0x03, ///< Abort receive and transmit - ABORT_RS = 0x04, ///< Abort uart and reset RS structure + ABORT_TX = 0x01, ///< Abort transmit + ABORT_RX = 0x02, ///< Abort receive + ABORT_RX_TX = 0x03, ///< Abort receive and transmit + ABORT_RS = 0x04, ///< Abort uart and reset RS structure }RS_AbortTypeDef; /** @brief Enums for RX Size modes */ -typedef enum // RS_RXSizeTypeDef +typedef enum // RS_RXSizeTypeDef { - RS_RX_Size_Const = 0x01, ///< size of receiving message is constant - RS_RX_Size_NotConst = 0x02, ///< size of receiving message isnt constant + RS_RX_Size_Const = 0x01, ///< size of receiving message is constant + RS_RX_Size_NotConst = 0x02, ///< size of receiving message isnt constant } RS_RX_SizeTypeDef; //-----------STRUCTURE FOR HANDLE RS------------ /** @brief Struct for flags RS */ typedef struct { - unsigned RX_Half:1; ///< flag: 0 - receiving msg before ByteCnt, 0 - receiving msg after ByteCnt - - unsigned RS_Busy:1; ///< flag: 1 - RS is busy, 0 - RS isnt busy - unsigned RX_Ongoing:1; ///< flag: 1 - receiving data right now, 0 - waiting for receiving data + unsigned RX_Half:1; ///< flag: 0 - receiving msg before ByteCnt, 0 - receiving msg after ByteCnt - unsigned RX_Busy:1; ///< flag: 1 - receiving is active, 0 - receiving isnt active - unsigned TX_Busy:1; ///< flag: 1 - transmiting is active, 0 - transmiting isnt active - - unsigned RX_Done:1; ///< flag: 1 - receiving is done, 0 - receiving isnt done - unsigned TX_Done:1; ///< flag: 1 - transmiting is done, 0 - transmiting isnt done - - // setted by user - 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 DeferredResponse:1; ///< flag: 1 - response not in interrupt, 0 - response in interrupt - unsigned ReInit_UART:1; ///< flag: 1 - need to reinitialize uart, 0 - nothing + unsigned RS_Busy:1; ///< flag: 1 - RS is busy, 0 - RS isnt busy + unsigned RX_Ongoing:1; ///< flag: 1 - receiving data right now, 0 - waiting for receiving data + + unsigned RX_Busy:1; ///< flag: 1 - receiving is active, 0 - receiving isnt active + unsigned TX_Busy:1; ///< flag: 1 - transmiting is active, 0 - transmiting isnt active + + unsigned RX_Done:1; ///< flag: 1 - receiving is done, 0 - receiving isnt done + unsigned TX_Done:1; ///< flag: 1 - transmiting is done, 0 - transmiting isnt done + + // setted by user + 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 DeferredResponse:1; ///< flag: 1 - response not in interrupt, 0 - response in interrupt + unsigned ReInit_UART:1; ///< flag: 1 - need to reinitialize uart, 0 - nothing }RS_FlagsTypeDef; /** - * @brief Handle for RS communication. - * @note Prefixes: h - handle, s - settings, f - flag - */ -typedef struct // RS_HandleTypeDef -{ - /* MESSAGE */ - uint8_t ID; ///< ID of RS "channel" - RS_MsgTypeDef *pMessagePtr; ///< pointer to message struct - uint8_t *pBufferPtr; ///< pointer to message buffer -#ifdef RS_IN_FREERTOS - uint16_t taskDelay; ///< freertos buffer + * @brief Handle for RS communication. + * @note Prefixes: h - handle, s - settings, f - flag + */ +typedef struct // RS_HandleTypeDef +{ + /* MESSAGE */ + uint8_t ID; ///< ID of RS "channel" + RS_MsgTypeDef *pMessagePtr; ///< pointer to message struct + uint8_t *pBufferPtr; ///< pointer to message buffer +#ifdef RS_IN_RTOS + uint16_t taskDelay; ///< freertos buffer #endif - uint32_t RS_Message_Size; ///< size of whole message, not only data - - /* HANDLERS and SETTINGS */ - uint8_t tx_pin; ///< Transmit pin - uint8_t rx_pin; ///< Receive pin - HUART_TypeDef *huart; ///< handler for used uart - RS_ModeTypeDef sRS_Mode; ///< setting: slave or master @ref RS_ModeTypeDef - uint16_t sRS_Timeout; ///< setting: timeout in ms - RS_RX_SizeTypeDef sRS_RX_Size_Mode; ///< setting: 1 - not const, 0 - const - - /* FLAGS */ - RS_FlagsTypeDef f; ///< These flags for controling receive/transmit + uint32_t RS_Message_Size; ///< size of whole message, not only data - /* RS STATUS */ + /* HANDLERS and SETTINGS */ + uint8_t tx_pin; ///< Transmit pin + uint8_t rx_pin; ///< Receive pin + HUART_TypeDef *huart; ///< handler for used uart + RS_ModeTypeDef sRS_Mode; ///< setting: slave or master @ref RS_ModeTypeDef + uint16_t sRS_Timeout; ///< setting: timeout in ms + RS_RX_SizeTypeDef sRS_RX_Size_Mode; ///< setting: 1 - not const, 0 - const + + /* FLAGS */ + RS_FlagsTypeDef f; ///< These flags for controling receive/transmit + + /* RS STATUS */ unsigned long lastByteTime; unsigned long baudRate; - RS_StatusTypeDef RS_STATUS; ///< RS status + RS_StatusTypeDef RS_STATUS; ///< RS status }RS_HandleTypeDef; extern RS_HandleTypeDef hmodbus1;