{"id":473119,"date":"2025-09-02T15:31:13","date_gmt":"2025-09-02T15:31:13","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=473119"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=473119","title":{"rendered":"<span>I2C Slave \u043d\u0430 STM32G4<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u043b\u043e\u0441\u044c \u043c\u043d\u0435 <s>\u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/s> \u043f\u043e \u043f\u0440\u0438\u043a\u043e\u043b\u0443 \u0441\u0434\u0435\u043b\u0430\u0442\u044c i2c slave (\u0432\u0435\u0434\u043e\u043c\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430), \u043d\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u044e \u043e\u0434\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 eeprom), \u0430 \u0441\u0440\u0430\u0437\u0443 \u044d\u0434\u0430\u043a\u043e\u0433\u043e \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0441, \u0435\u0441\u043b\u0438 \u043c\u043e\u0436\u043d\u043e \u044d\u0442\u043e \u0442\u0430\u043a \u043d\u0430\u0437\u0432\u0430\u0442\u044c, API, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0443\u0436\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0430\u0434\u0440\u0435\u0441\u0430.<\/p>\n<p>\u041d\u0430 \u0442\u0435\u043c\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0435\u0434\u043e\u043c\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u043d\u0430 STM32 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c LL \u044f \u043a\u0430\u043a-\u0442\u043e \u043d\u0435 \u043e\u0441\u043e\u0431\u043e \u043c\u043d\u043e\u0433\u043e \u0438\u043d\u0444\u044b \u043d\u0430\u0440\u044b\u043b, \u0432 \u0438\u0442\u043e\u0433\u0435 \u043d\u0430\u043a\u043e\u0441\u0442\u044b\u043b\u0438\u043b, \u043a\u0430\u043a \u0441\u0430\u043c \u043f\u043e\u043d\u044f\u043b \ud83d\ude00 \u0422\u0435\u0441\u0442 \u043e\u0442\u0432\u0451\u0440\u0442\u043a\u043e\u0439 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442, \u0445\u043e\u0442\u044f \u043f\u0435\u0440\u0432\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u043e\u0433\u0434\u0430 \u043f\u0440\u044f\u043c \u0437\u0430\u043b\u0438\u043f\u0430\u043b\u0438 \u043d\u0430\u043c\u0435\u0440\u0442\u0432\u043e.<\/p>\n<p>\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u0433\u043b\u0443\u0431\u043e\u043a\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u044b, \u0441\u0430\u043c\u0443 \u0440\u0430\u0431\u043e\u0442\u0443 \u0448\u0438\u043d\u044b, \u043f\u0440\u043e\u0447\u0435\u0435, \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0431\u0440\u0430 \u043d\u0430\u0432\u0430\u043b\u043e\u043c. \u041f\u0440\u043e\u0441\u0442\u043e \u043e\u043a\u0443\u043d\u0451\u043c\u0441\u044f \u0432 <s>\u0434\u0438\u043f \u0434\u0430\u0440\u043a \u0444\u044d\u043d\u0442\u0435\u0437\u0438<\/s> \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0435\u0433\u043e \u0442\u0430\u0447\u0430 <strong>cst816s.<\/strong><\/p>\n<p>\u0414\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u0441\u0442\u0435\u043d\u0434:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d3c\/676\/9a0\/d3c6769a0aac12fed5034495cf0d35b3.png\" alt=\"\u0411\u043b\u043e\u043a-\u0441\u0445\u0435\u043c\u0430 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043d\u0430 \u0441\u0442\u043e\u043b\u0435 \u043c\u0430\u043a\u0435\u0442\u0430\" title=\"\u0411\u043b\u043e\u043a-\u0441\u0445\u0435\u043c\u0430 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043d\u0430 \u0441\u0442\u043e\u043b\u0435 \u043c\u0430\u043a\u0435\u0442\u0430\" width=\"641\" height=\"481\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d3c\/676\/9a0\/d3c6769a0aac12fed5034495cf0d35b3.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d3c\/676\/9a0\/d3c6769a0aac12fed5034495cf0d35b3.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0411\u043b\u043e\u043a-\u0441\u0445\u0435\u043c\u0430 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043d\u0430 \u0441\u0442\u043e\u043b\u0435 \u043c\u0430\u043a\u0435\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043c\u0430\u0441\u0442\u0435\u0440-\u043f\u043b\u0430\u0442\u044b \u0437\u0434\u0435\u0441\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u0442, \u0435\u0441\u043b\u0438 \u043e\u0447\u0435\u043d\u044c \u043d\u0430\u0434\u043e, \u0442\u043e \u043c\u043e\u0433\u0443 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0434\u0440\u0430\u0439\u0432\u0435\u0440 LCD \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 LVGL.<\/em><\/p>\n<h2>I2C Slave<\/h2>\n<p>\u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0431\u0430\u0437\u044b. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442 \u2014 \u044d\u0442\u043e <strong>i2c_slave<\/strong> \u0444\u0430\u0439\u043b\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0441\u0430\u043c\u044b\u0439 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u0434 \u043f\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0439 \u0438 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0435\u0434\u043e\u043c\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432. \u042d\u0442\u043e\u0442 \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442 \u0443\u043c\u0435\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u043c\u0430\u0441\u0442\u0435\u0440\u0443 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e, \u0434\u0430\u0436\u0435 \u0431\u0435\u0437 \u0435\u0434\u0438\u043d\u043e\u0439 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432, \u0449\u0435\u0434\u0440\u043e \u0432\u044b\u0432\u0430\u043b\u0438\u0432\u0430\u044f \u0432\u0441\u0451 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0435 \u0432 \u043b\u043e\u0433 (Segger RTT).<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e \u0432 \u0432\u0438\u0434\u0435 \u0431\u043b\u043e\u043a-\u0441\u0445\u0435\u043c\u044b, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/51d\/f4e\/487\/51df4e48728692f74a3356d6e8de6091.png\" alt=\"wtf\" title=\"wtf\" width=\"361\" height=\"361\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/51d\/f4e\/487\/51df4e48728692f74a3356d6e8de6091.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/51d\/f4e\/487\/51df4e48728692f74a3356d6e8de6091.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>wtf<\/figcaption><\/div>\n<\/figure>\n<div class=\"floating-image\">\n<p><strong>i2c_slave.h<\/strong><\/p>\n<\/div>\n<p>\u0412 \u0445\u0435\u0434\u0435\u0440\u0435 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0433\u043e. \u0414\u0435\u0444\u0430\u0439\u043d\u044b \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b:<\/p>\n<ul>\n<li>\n<p><strong>I2C_SLAVE_SLAVES_MAX <\/strong>\u2014 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432<\/p>\n<\/li>\n<li>\n<p> <strong>I2C_SLAVE_HW_DEBUG_LOG <\/strong>\u2014 \u043a\u0443\u0447\u0430 \u0434\u0435\u0431\u0430\u0433 \u0438\u043d\u0444\u044b \u0432 RTT<\/p>\n<\/li>\n<li>\n<p><strong>slave_instance_t <\/strong>\u2014 &#171;\u0441\u0441\u044b\u043b\u043a\u0430&#187; \u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430<\/p>\n<\/li>\n<li>\n<p><strong>i2c_slave_t <\/strong>\u2014 \u043a\u043e\u043d\u0444\u0438\u0433 \u0441\u0430\u043c\u043e\u0433\u043e i2c_slave (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e, \u043f\u043e\u0434 \u043a\u0430\u0436\u0434\u044b\u0439 \u0445\u0430\u0440\u0434\u0432\u0430\u0440\u043d\u044b\u0439 i2c)<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0435 \u0438\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n<ul>\n<li>\n<p><strong>i2cSlave_Init <\/strong>\u2014 \u0431\u0430\u0437\u043e\u0432\u0430\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/p>\n<\/li>\n<li>\n<p><strong>i2cSlave_Enable <\/strong>\\ <strong>i2cSlave_Disable <\/strong>\u2014 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 i2c_slave (\u043f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043d\u0435 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u0442\u0441\u044f, \u0442.\u043a. \u0431\u044b\u0432\u0430\u044e\u0442 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0431\u044b\u0442\u044c \u043d\u0430 \u0448\u0438\u043d\u0435 \u043c\u0430\u0441\u0442\u0435\u0440\u043e\u043c, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c \u0432\u0435\u0434\u043e\u043c\u043e\u0433\u043e)<\/p>\n<\/li>\n<li>\n<p><strong>i2cSlave_Register <\/strong>\u2014 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f (\u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0441\u044b\u043b\u043a\u0438) \u043d\u043e\u0432\u043e\u0433\u043e \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u043e\u043b\u0431\u0435\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0436\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u0437 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u0435\u0440\u0438\u0444\u0435\u0440\u0438\u0438 (\u0432 \u043c\u043e\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 i2c \u043d\u0430 LL \u0432 \u0440\u0435\u0436\u0438\u043c\u0430 \u043c\u0430\u0441\u0442\u0435\u0440\u0430 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f):<\/p>\n<ul>\n<li>\n<p><strong>i2cSlave_IrqAddrSet <\/strong>\u2014 \u043d\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0442 \u043c\u0430\u0441\u0442\u0435\u0440\u0430 \u0441 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u0432\u0435\u0434\u043e\u043c\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430<\/p>\n<\/li>\n<li>\n<p><strong>i2cSlave_IrqRecive <\/strong>\u2014 \u043f\u0440\u0438\u043d\u044f\u0442 \u0431\u0430\u0439\u0442<\/p>\n<\/li>\n<li>\n<p><strong>i2cSlave_IrqTransmit <\/strong>\u2014 \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d \u0431\u0430\u0439\u0442<\/p>\n<\/li>\n<li>\n<p><strong>i2cSlave_IrqNack <\/strong>\u2014 \u043f\u043e\u043b\u0443\u0447\u0435\u043d NACK<\/p>\n<\/li>\n<li>\n<p><strong>i2cSlave_IrqError <\/strong>\u2014 \u043e\u0448\u0438\u0431\u043a\u0430 \u043d\u0430 \u0448\u0438\u043d\u0435<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u0437 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0439, \u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0438\u0436\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>#ifndef _I2C_SLAVE_H_ #define _I2C_SLAVE_H_  \/* ----------------------------------------------------------------------------------------------------------------- \/\/ v0.10 - 2025.07.20: - \u041f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f  v0.11 - 2025.07.21: - \u041c\u0435\u043b\u043a\u0438\u0435 \u043f\u0440\u0430\u0432\u043a\u0438, \u0432\u0440\u043e\u0434\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442  \/\/ ----------------------------------------------------------------------------------------------------------------- *\/  #include \"main.h\"  #ifndef I2C_SLAVE_SLAVES_MAX #define I2C_SLAVE_SLAVES_MAX          20 #endif  #define I2C_SLAVE_LOG_PREFIX          \"[i2c_slv] \"  #ifndef I2C_SLAVE_HW_DEBUG_LOG #define I2C_SLAVE_HW_DEBUG_LOG        0 #endif  typedef struct __attribute__((__packed__)) {    uint8_t addr;    void *conf;    void (*freg)(void *, uint8_t);    void (*fwrite)(void *, uint8_t);    void (*fread)(void *, uint8_t *);    void (*fdone)(void *); } slave_instance_t;  typedef struct __attribute__((__packed__)) {    uint8_t inited;    uint8_t addr;    uint8_t reg;    uint8_t slave_num;    uint8_t slave_id;    void *i2c;    slave_instance_t slave[I2C_SLAVE_SLAVES_MAX]; } i2c_slave_t;  uint32_t i2cSlave_Init(i2c_slave_t *conf, void *hi2c); void i2cSlave_Enable(i2c_slave_t *conf); void i2cSlave_Disable(i2c_slave_t *conf); uint32_t i2cSlave_Register(i2c_slave_t *conf, uint8_t slave_addr, void *slave_conf, void *freg, void *fwrite, void *fread, void *fdone);  \/\/ Call in Interrupt uint32_t i2cSlave_IrqAddrSet(i2c_slave_t *conf, uint8_t addr); void i2cSlave_IrqRecive(i2c_slave_t *conf); void i2cSlave_IrqTransmit(i2c_slave_t *conf); void i2cSlave_IrqComplete(i2c_slave_t *conf); void i2cSlave_IrqNack(i2c_slave_t *conf); void i2cSlave_IrqError(i2c_slave_t *conf);  #endif \/\/ _I2C_SLAVE_H_<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>i2c_slave.c<\/strong><\/p>\n<p>\u0412 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0436\u0435 \u043e\u0441\u043e\u0431\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u043e\u0433\u043e, \u043d\u043e \u0435\u0441\u0442\u044c-\u0442\u0430\u043a\u0438 \u043f\u0430\u0440\u0430 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432:<\/p>\n<ul>\n<li>\n<p>i2c_slave \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u0432\u0441\u0435 \u0430\u0434\u0440\u0435\u0441\u0430, \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u044b\u0435 \u043c\u0430\u0441\u043a\u043e\u0439 (\u0430 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u0443 \u043c\u0430\u0441\u0442\u0435\u0440\u0430 \u043c\u043e\u0436\u0435\u0442 \u0441\u0431\u043e\u0438\u0442\u044c \u0438 &#171;\u0432\u0438\u0434\u0435\u0442\u044c&#187; \u043a\u0443\u0447\u0443 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u043d\u0430 \u0448\u0438\u043d\u0435), \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u044d\u0442\u043e \u0442\u0430\u043a:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d37\/902\/b16\/d37902b16d2392e9b0df68a2588e3329.png\" alt=\"\u041c\u0430\u0441\u0442\u0435\u0440 \u0441\u043a\u0430\u043d\u0438\u0442 \u0448\u0438\u043d\u0443 \u0438 \u0432\u0438\u0434\u0438\u0442 \u0438\u043b\u043b\u044e\u0437\u0438\u044e \u0438\u0437\u043e\u0431\u0438\u043b\u0438\u044f \u0432\u0435\u0434\u043e\u043c\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u043e\u043b\u044c\u043a\u043e 0x15\" title=\"\u041c\u0430\u0441\u0442\u0435\u0440 \u0441\u043a\u0430\u043d\u0438\u0442 \u0448\u0438\u043d\u0443 \u0438 \u0432\u0438\u0434\u0438\u0442 \u0438\u043b\u043b\u044e\u0437\u0438\u044e \u0438\u0437\u043e\u0431\u0438\u043b\u0438\u044f \u0432\u0435\u0434\u043e\u043c\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u043e\u043b\u044c\u043a\u043e 0x15\" width=\"843\" height=\"748\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d37\/902\/b16\/d37902b16d2392e9b0df68a2588e3329.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d37\/902\/b16\/d37902b16d2392e9b0df68a2588e3329.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041c\u0430\u0441\u0442\u0435\u0440 \u0441\u043a\u0430\u043d\u0438\u0442 \u0448\u0438\u043d\u0443 \u0438 \u0432\u0438\u0434\u0438\u0442 \u0438\u043b\u043b\u044e\u0437\u0438\u044e \u0438\u0437\u043e\u0431\u0438\u043b\u0438\u044f \u0432\u0435\u0434\u043e\u043c\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u043e\u043b\u044c\u043a\u043e 0x15<\/figcaption><\/div>\n<\/figure>\n<\/li>\n<li>\n<p>\u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430, \u0430 \u043c\u0430\u0441\u0442\u0435\u0440 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0431\u0430\u0439\u0442, \u0442\u043e i2c_slave \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u043c\u0443 0xFF \u0432\u0441\u0435\u0433\u0434\u0430<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>#include \"i2c_slave.h\" #include &lt;string.h&gt;  uint32_t i2cSlave_Init(i2c_slave_t *conf, void *hi2c) {    conf-&gt;i2c = hi2c;    conf-&gt;inited = 1;    conf-&gt;slave_num = 0;    conf-&gt;slave_id = 0xff;    conf-&gt;reg = 0;     for (uint8_t i = 0; i &lt; I2C_SLAVE_SLAVES_MAX; i++)    {       conf-&gt;slave[i].addr = 0xff;    }     \/\/ TODO: \u043a\u0440\u0438\u0432\u043e\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435, \u043d\u043e \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0437\u0430\u0434\u0430\u0447 \u043f\u043e\u0439\u0434\u0451\u0442    SysView_LogSuccess(\"\\r\\n\" I2C_SLAVE_LOG_PREFIX \"Inited at I2C%u\\r\\n\", (hi2c == I2C1) ? 1 : 2);    return 0x00; }  void i2cSlave_Enable(i2c_slave_t *conf) {    if (conf-&gt;inited)    {       LL_I2C_SetOwnAddress1(conf-&gt;i2c, (0x01 &lt;&lt; 1), LL_I2C_OWNADDRESS1_7BIT);       LL_I2C_SetOwnAddress2(conf-&gt;i2c, (0x00 &lt;&lt; 1), LL_I2C_OWNADDRESS2_MASK07); \/\/ 7 bit only compare       LL_I2C_EnableOwnAddress1(conf-&gt;i2c);       LL_I2C_EnableOwnAddress2(conf-&gt;i2c);        LL_I2C_EnableIT_RX(conf-&gt;i2c);       LL_I2C_EnableIT_TX(conf-&gt;i2c);       LL_I2C_EnableIT_ADDR(conf-&gt;i2c);       LL_I2C_EnableIT_NACK(conf-&gt;i2c);       LL_I2C_EnableIT_ERR(conf-&gt;i2c);       LL_I2C_EnableIT_STOP(conf-&gt;i2c);        SysView_LogInfo(I2C_SLAVE_LOG_PREFIX \"Enabled\\r\\n\");    } }  void i2cSlave_Disable(i2c_slave_t *conf) {    if (conf-&gt;inited)    {       LL_I2C_DisableOwnAddress1(conf-&gt;i2c);       LL_I2C_DisableOwnAddress2(conf-&gt;i2c);        LL_I2C_DisableIT_RX(conf-&gt;i2c);       LL_I2C_DisableIT_TX(conf-&gt;i2c);       LL_I2C_DisableIT_ADDR(conf-&gt;i2c);       LL_I2C_DisableIT_NACK(conf-&gt;i2c);       LL_I2C_DisableIT_ERR(conf-&gt;i2c);       LL_I2C_DisableIT_STOP(conf-&gt;i2c);        conf-&gt;slave_id = 0xff;       conf-&gt;reg = 0;       SysView_LogInfo(I2C_SLAVE_LOG_PREFIX \"Disabled\\r\\n\");    } }  uint32_t i2cSlave_Register(i2c_slave_t *conf, uint8_t slave_addr, void *slave_conf, void *freg, void *fwrite, void *fread, void *fdone) {    if (conf-&gt;inited)    {       if (conf-&gt;slave_num &lt; (I2C_SLAVE_SLAVES_MAX - 1))       {          for (uint8_t i = 0; i &lt; conf-&gt;slave_num; i++)          {             if (conf-&gt;slave[i].addr == slave_addr)             {                SysView_LogWarning(I2C_SLAVE_LOG_PREFIX \"0x%x already registered at id = %u! Skip\\r\\n\", slave_addr, i);                return 0x01;             }          }           SysView_LogInfo(I2C_SLAVE_LOG_PREFIX \"Registered: addr = 0x%x, id = %u\\r\\n\", slave_addr, conf-&gt;slave_num);          conf-&gt;slave[conf-&gt;slave_num].addr = slave_addr;          conf-&gt;slave[conf-&gt;slave_num].conf = slave_conf;          conf-&gt;slave[conf-&gt;slave_num].freg = freg;          conf-&gt;slave[conf-&gt;slave_num].fwrite = fwrite;          conf-&gt;slave[conf-&gt;slave_num].fread = fread;          conf-&gt;slave[conf-&gt;slave_num].fdone = fdone;          conf-&gt;slave_num++;          return 0x00;       }    }     return 0x01; }  uint32_t i2cSlave_IrqAddrSet(i2c_slave_t *conf, uint8_t addr) {    if (conf-&gt;inited)    { #if (I2C_SLAVE_HW_DEBUG_LOG)       SysView_LogInfo(I2C_SLAVE_LOG_PREFIX \"Addr 0x%x: \", addr); #endif       conf-&gt;addr = addr;       conf-&gt;reg = 0;       conf-&gt;slave_id = 0xff;       for (uint8_t i = 0; i &lt; conf-&gt;slave_num; i++)       {          if (conf-&gt;slave[i].addr == conf-&gt;addr)          {             conf-&gt;slave_id = i; #if (I2C_SLAVE_HW_DEBUG_LOG)             SysView_LogInfo(\"id = 0x%x\\r\\n\", conf-&gt;slave_id); #endif             return 0x00;          }       }        if (conf-&gt;slave_id == 0xff)       { #if (I2C_SLAVE_HW_DEBUG_LOG)          SysView_LogWarning(\"not found\\r\\n\"); #endif       }    }     return 0x01; }  void i2cSlave_IrqRecive(i2c_slave_t *conf) {    if (conf-&gt;inited)    {       uint8_t data = LL_I2C_ReceiveData8(conf-&gt;i2c);       if (conf-&gt;slave_id != 0xff)       {          if (conf-&gt;reg == 0)          { #if (I2C_SLAVE_HW_DEBUG_LOG)             SysView_LogInfo(I2C_SLAVE_LOG_PREFIX \"Reg = 0x%x\\r\\n\", data); #endif             conf-&gt;reg = 1;             conf-&gt;slave[conf-&gt;slave_id].freg(conf-&gt;slave[conf-&gt;slave_id].conf, data);          }          else          { #if (I2C_SLAVE_HW_DEBUG_LOG)             SysView_LogInfo(I2C_SLAVE_LOG_PREFIX \"Write 0x%x\\r\\n\", data); #endif             conf-&gt;slave[conf-&gt;slave_id].fwrite(conf-&gt;slave[conf-&gt;slave_id].conf, data);          }       }       else       {          SysView_LogWarning(I2C_SLAVE_LOG_PREFIX \"Write skip 0x%x\\r\\n\", data);       }    } }  void i2cSlave_IrqTransmit(i2c_slave_t *conf) {    if (conf-&gt;inited)    {       if (conf-&gt;slave_id != 0xff)       {          static uint8_t data;          data = 0x00;          conf-&gt;slave[conf-&gt;slave_id].fread(conf-&gt;slave[conf-&gt;slave_id].conf, &amp;data); #if (I2C_SLAVE_HW_DEBUG_LOG)          SysView_LogInfo(I2C_SLAVE_LOG_PREFIX \"Read 0x%x\\r\\n\", data); #endif          LL_I2C_TransmitData8(conf-&gt;i2c, data);          return ;       }  #if (I2C_SLAVE_HW_DEBUG_LOG)       SysView_LogWarning(I2C_SLAVE_LOG_PREFIX \"Read skip\\r\\n\"); #endif       LL_I2C_TransmitData8(conf-&gt;i2c, 0xff);    } }  void i2cSlave_IrqComplete(i2c_slave_t *conf) {    if (conf-&gt;inited)    { #if (I2C_SLAVE_HW_DEBUG_LOG)       SysView_LogSuccess(I2C_SLAVE_LOG_PREFIX \"Complete\\r\\n\"); #endif       conf-&gt;addr = 0xff;       conf-&gt;reg = 0;       if (conf-&gt;slave_id != 0xff)       {          conf-&gt;slave[conf-&gt;slave_id].fdone(conf-&gt;slave[conf-&gt;slave_id].conf);       }        conf-&gt;slave_id = 0xff;    } }  void i2cSlave_IrqNack(i2c_slave_t *conf) {    if (conf-&gt;inited)    { #if (I2C_SLAVE_HW_DEBUG_LOG)       SysView_LogWarning(I2C_SLAVE_LOG_PREFIX \"NACK\\r\\n\"); #endif       conf-&gt;addr = 0xff;       conf-&gt;reg = 0;       if (conf-&gt;slave_id != 0xff)       {          conf-&gt;slave[conf-&gt;slave_id].fdone(conf-&gt;slave[conf-&gt;slave_id].conf);       }        conf-&gt;slave_id = 0xff;    } }  void i2cSlave_IrqError(i2c_slave_t *conf) {    if (conf-&gt;inited)    {       LL_I2C_Disable(conf-&gt;i2c);       LL_I2C_Enable(conf-&gt;i2c); #if (I2C_SLAVE_HW_DEBUG_LOG)       SysView_LogError(I2C_SLAVE_LOG_PREFIX \"Error\\r\\n\"); #endif       conf-&gt;addr = 0xff;       conf-&gt;reg = 0;       if (conf-&gt;slave_id != 0xff)       {          conf-&gt;slave[conf-&gt;slave_id].fdone(conf-&gt;slave[conf-&gt;slave_id].conf);       }        conf-&gt;slave_id = 0xff;    } }<\/code><\/pre>\n<\/div>\n<\/details>\n<h2>cst816s<\/h2>\n<p>\u0422\u0443\u0442 \u043e\u0441\u043e\u0431\u043e \u0438 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0435\u0447\u0435\u0433\u043e, \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u043d\u043d\u0430\u044f \u043f\u043e\u0434 \u0441\u0435\u0431\u044f \u0432\u0435\u0440\u0441\u0438\u044f, \u0432\u0437\u044f\u0442\u0430\u044f \u0441 <a href=\"https:\/\/www.waveshare.com\/wiki\/1.28inch_Touch_LCD\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0438\u043c\u0435\u0440\u0430 WaveShare<\/a>.<\/p>\n<p><strong>cst816s.h<\/strong><\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>#ifndef _CST816S_H_ #define _CST816S_H_  \/* ----------------------------------------------------------------------------------------------------------------- \/\/ v0.10 - 2025.03.23: - \u041f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f  v0.11 - 2025.05.20: - \u041f\u0440\u0430\u0432\u043a\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0441\u0442\u0430\u0442\u0443\u0441\u043e\u0432 - \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 target_common.h  \/\/ ----------------------------------------------------------------------------------------------------------------- *\/  #include \"main.h\"  #ifndef CST816S_TIMEOUT_MS #define CST816S_TIMEOUT_MS                         500 #endif  #ifndef CST816S_DEFAULT_ADDRESS #define CST816S_DEFAULT_ADDRESS                    0x15 #endif  #ifndef CST816S_RESET_PIN_ENABLE #define CST816S_RESET_PIN_ENABLE                   0 #endif  #ifndef CST816S_DEBUG_SHOW_RAW_EVENTS #define CST816S_DEBUG_SHOW_RAW_EVENTS              0 #endif  #define CST816S_LOG_PREFIX                         \"[cst816s] \"  typedef enum {    CST816S_GESTURE_NONE = 0x00,    CST816S_GESTURE_SWIPE_UP = 0x01,    CST816S_GESTURE_SWIPE_DOWN = 0x02,    CST816S_GESTURE_SWIPE_LEFT = 0x03,    CST816S_GESTURE_SWIPE_RIGHT = 0x04,    CST816S_GESTURE_SINGLE_CLICK = 0x05,    CST816S_GESTURE_DOUBLE_CLICK = 0x0B,    CST816S_GESTURE_LONG_PRESS = 0x0C } cst816s_gesture_t;  typedef enum {    CST816S_EVENT_DOWN = 0x00,    CST816S_EVENT_UP,    CST816S_EVENT_CONTACT, } cst816s_event_type_t;  typedef struct __attribute__((__packed__)) {    uint16_t x;    uint16_t y; } cst816s_event_t;  typedef struct __attribute__((__packed__)) {    uint8_t address;    uint8_t inited;    uint8_t gesture; \/\/ cst816s_gesture_t    uint8_t event_type; \/\/ cst816s_event_type_t    cst816s_event_t event; #if (CST816S_RESET_PIN_ENABLE)    void *reset_port;    uint16_t reset_pin; #endif    void *i2c; } cst816s_touch_t;  uint8_t cst816s_Init(cst816s_touch_t *conf, void *hi2c, uint8_t address); uint8_t cst816s_SetAutoSleep(cst816s_touch_t *conf, uint8_t enable, uint8_t sec); uint8_t cst816s_ReadVersion(cst816s_touch_t *conf); uint8_t cst816s_ReadEvent(cst816s_touch_t *conf);  #endif \/\/ _CST816S_H_ <\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>cst816s.c<\/strong><\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>#include \"cst816s.h\" #include \"target_delay.h\" #include \"target_gpio.h\" #include \"target_i2c.h\"  __inline uint32_t cst816s_RegWrite(cst816s_touch_t *conf, uint8_t reg, uint8_t data) {    return target_I2C_WriteByte(conf-&gt;i2c, conf-&gt;address, reg, TARGET_I2C_REG_LEN_BYTE, data, CST816S_TIMEOUT_MS); }  __inline uint32_t cst816s_RegRead(cst816s_touch_t *conf, uint8_t reg, uint8_t *data) {    return target_I2C_ReadByte(conf-&gt;i2c, conf-&gt;address, reg, TARGET_I2C_REG_LEN_BYTE, data, CST816S_TIMEOUT_MS); }  uint8_t cst816s_Init(cst816s_touch_t *conf, void *hi2c, uint8_t address) {    conf-&gt;i2c = hi2c;    conf-&gt;address = (address &lt;&lt; 1);    conf-&gt;inited = 0;  #if (CST816S_RESET_PIN_ENABLE)    target_ResetPin(conf-&gt;reset_port, conf-&gt;reset_pin);    target_Delay_ms(1);    target_SetPin(conf-&gt;reset_port, conf-&gt;reset_pin);    target_Delay_ms(10); #endif     if (target_I2C_IsDeviceReady(conf-&gt;i2c, conf-&gt;address, CST816S_TIMEOUT_MS) == 0x00)    {       conf-&gt;inited = 1;       SysView_LogSuccess(\"\\r\\n\"CST816S_LOG_PREFIX \"Inited (addr 0x%x)\\r\\n\", address);       cst816s_ReadVersion(conf);       cst816s_RegWrite(conf, 0xEC, 1); \/\/ Enable double-tap       cst816s_SetAutoSleep(conf, 0, 255); \/\/ Disable auto sleep       return STATUS_OK;    }     SysView_LogWarning(\"\\r\\n\"CST816S_LOG_PREFIX \"Init failed (addr 0x%x)\\r\\n\", address);    return STATUS_BUSY; }  uint8_t cst816s_SetAutoSleep(cst816s_touch_t *conf, uint8_t enable, uint8_t sec) {    if (conf-&gt;inited)    {       uint32_t status = STATUS_OK;       if (enable)       {          SysView_LogInfo(CST816S_LOG_PREFIX \"Auto sleep enabled, timeout %u sec\\r\\n\", sec);          status  = cst816s_RegWrite(conf, 0xFE, 0x00);          status |= cst816s_RegWrite(conf, 0xF9, sec);       }       else       {          SysView_LogInfo(CST816S_LOG_PREFIX \"Auto sleep disabled\\r\\n\");          status = cst816s_RegWrite(conf, 0xFE, 0xFE);       }        return status;    }     return STATUS_ERROR; }  uint8_t cst816s_ReadVersion(cst816s_touch_t *conf) {    if (conf-&gt;inited)    {       uint8_t data[3] = { 0 };       uint32_t status = STATUS_OK;        status  = cst816s_RegRead(conf, 0xA7, &amp;data[0]); \/\/ ChipID       status |= cst816s_RegRead(conf, 0xA8, &amp;data[1]); \/\/ ProjID       status |= cst816s_RegRead(conf, 0xA9, &amp;data[2]); \/\/ Firmware        SysView_LogInfo(CST816S_LOG_PREFIX \"Chip ID: 0x%x\\r\\n\", data[0]);       SysView_LogInfo(CST816S_LOG_PREFIX \"Project ID: 0x%x\\r\\n\", data[1]);       SysView_LogInfo(CST816S_LOG_PREFIX \"Firmware: 0x%x\\r\\n\", data[2]);        return status;    }     return STATUS_ERROR; }  uint8_t cst816s_ReadEvent(cst816s_touch_t *conf) {    if (conf-&gt;inited)    {       uint8_t data[6];       uint32_t status = target_I2C_ReadMem(conf-&gt;i2c, conf-&gt;address, 0x01, TARGET_I2C_REG_LEN_BYTE, &amp;data[0], 6, CST816S_TIMEOUT_MS);        conf-&gt;gesture = data[0];       \/\/points = data[1];       conf-&gt;event_type = data[2] &gt;&gt; 6;       conf-&gt;event.x = ((data[2] &amp; 0xF) &lt;&lt; 8) + data[3];       conf-&gt;event.y = ((data[4] &amp; 0xF) &lt;&lt; 8) + data[5];  #if (CST816S_DEBUG_SHOW_RAW_EVENTS)       SysView_LogInfo(CST816S_LOG_PREFIX \"Event: X=%03u Y=%03u\\r\\n\", conf-&gt;event.x, conf-&gt;event.y);       if (conf-&gt;gesture)       {          SysView_LogInfo(CST816S_LOG_PREFIX \"Gesture: 0x%x\\r\\n\", conf-&gt;gesture);       } #endif       return status;    }     return STATUS_ERROR; } <\/code><\/pre>\n<\/div>\n<\/details>\n<h2>cst816s_emu<\/h2>\n<p>\u0410 \u0442\u0443\u0442 \u0443\u0436\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435, \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043b \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0432\u044b\u0448\u0435, \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043b \u0438 \u0441\u0442\u0430\u043b \u0434\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c. \u0427\u0435\u0433\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u043b\u043e\u0441\u044c\\\u043f\u043e\u044f\u0432\u0438\u043b\u043e\u0441\u044c:<\/p>\n<ul>\n<li>\n<p>\u0412\u043d\u0430\u0447\u0430\u043b\u0435 \u043c\u0430\u0441\u0442\u0435\u0440 \u043e\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0442\u0430\u0447 \u0438 \u0447\u0438\u0442\u0430\u0435\u0442 \u0441 \u043d\u0435\u0433\u043e Chip ID, Proj ID \u0438 Firmware Version, \u0442\u0430\u043a \u0432\u043e\u0442, \u043f\u0435\u0440\u0432\u044b\u0435 \u0434\u0432\u0430 \u044f \u043e\u0441\u0442\u0430\u0432\u0438\u043b \u043a\u0430\u043a \u0432 \u0447\u0438\u043f\u0435, \u0430 Firmware \u043f\u043e\u043c\u0435\u043d\u044f\u043b \u043d\u0430 0x69 (\u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u043e\u0442 \u0445\u0430\u0440\u0434\u0432\u0430\u0440\u043d\u043e\u0433\u043e \u0447\u0438\u043f\u0430)<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 I2C Slave API, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0442\u043e\u043c \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c<\/p>\n<\/li>\n<li>\n<p><strong>cst816s_emu_NewEvent <\/strong>\u2014 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0438 \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c &#171;\u0433\u0435\u043d\u0435\u0440\u0438\u043c&#187; \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f (\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 int \u043f\u0438\u043d\u0435, \u0438 \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043e\u0442 \u043c\u0430\u0441\u0442\u0435\u0440\u0430 \u0432\u044b\u0434\u0430\u0451\u043c \u0435\u043c\u0443 <strong>x,y,<\/strong> \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u044b \u0432 \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e)<\/p>\n<\/li>\n<\/ul>\n<p><strong>cst816s_emu.h<\/strong><\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>#ifndef _CST816S_EMU_H_ #define _CST816S_EMU_H_  \/* ----------------------------------------------------------------------------------------------------------------- \/\/ v0.10 - 2025.07.20: - \u041f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 cst816s.h \u0438\u0437 LLSDK  \/\/ ----------------------------------------------------------------------------------------------------------------- *\/  #include \"main.h\" #include \"cst816s.h\" #include \"i2c_slave.h\"  #ifndef CST816S_EMU_TIMEOUT_MS #define CST816S_EMU_TIMEOUT_MS                  100 #endif  #ifndef CST816S_EMU_DEFAULT_ADDRESS #define CST816S_EMU_DEFAULT_ADDRESS             0x15 #endif  #ifndef CST816S_EMU_DEBUG_SHOW_RAW_EVENTS #define CST816S_EMU_DEBUG_SHOW_RAW_EVENTS       0 #endif  #define CST816S_EMU_CHIP_ID                     0xb6 \/\/ 0xA7 #define CST816S_EMU_PROJECT_ID                  0x02 \/\/ 0xA8 #define CST816S_EMU_FIRMWARE_VER                0x69 \/\/ 0xA9  #define CST816S_EMU_LOG_PREFIX                  \"[cst816s_emu] \"  typedef struct __attribute__((__packed__)) {    uint8_t address;    uint8_t inited;    uint8_t reg_addr;    uint8_t event_new;    uint32_t event_time;    cst816s_event_t event;    void *int_port;    uint16_t int_pin;    void *i2c; } cst816s_emu_touch_t;  uint32_t cst816s_emu_Init(cst816s_emu_touch_t *conf, void *hi2c, uint8_t address); uint32_t cst816s_emu_NewEvent(cst816s_emu_touch_t *conf, uint16_t x, uint16_t y); void cst816s_emu_Routine(cst816s_emu_touch_t *conf);  \/\/ I2C Slave API void cst816s_emu_Reg(cst816s_emu_touch_t *conf, uint8_t data); void cst816s_emu_Write(cst816s_emu_touch_t *conf, uint8_t data); void cst816s_emu_Read(cst816s_emu_touch_t *conf, uint8_t *data); void cst816s_emu_Done(cst816s_emu_touch_t *conf);  #endif \/\/ _CST816S_EMU_H_ <\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>cst816s_emu.c<\/strong><\/p>\n<p>\u0418\u0437 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0433\u043e \u0437\u0434\u0435\u0441\u044c, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <strong>cst816s_emu_Read<\/strong>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b, \u0441\u0447\u0438\u0442\u0430\u0439, \u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u043c \u0430\u0434\u0440\u0435\u0441\u043e\u043c (\u0438 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435\u043c, \u043e\u0442\u043a\u0443\u0434\u0430 \u043c\u0430\u0441\u0442\u0435\u0440 \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0438\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435), \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043d\u0435\u0448\u0442\u0430\u0442\u043d\u044b\u0435 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438 (\u043a\u043e\u0433\u0434\u0430 \u043c\u0430\u0441\u0442\u0435\u0440 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u043d\u0435 \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0441\u0438\u043c\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u043e\u0432).<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>#include \"cst816s_emu.h\" #include \"target_gpio.h\" #include \"target_delay.h\"  uint32_t cst816s_emu_Init(cst816s_emu_touch_t *conf, void *hi2c, uint8_t address) {    conf-&gt;i2c = hi2c;    conf-&gt;address = (address &lt;&lt; 1);    conf-&gt;inited = 1;    conf-&gt;event_new = 0;    target_SetPin(conf-&gt;int_port, conf-&gt;int_pin);    SysView_LogSuccess(\"\\r\\n\"CST816S_EMU_LOG_PREFIX \"Inited (addr 0x%x)\\r\\n\", address);    return STATUS_OK; }  uint32_t cst816s_emu_NewEvent(cst816s_emu_touch_t *conf, uint16_t x, uint16_t y) {    if (conf-&gt;inited)    {       if (conf-&gt;event_new == 0)       {          SysView_LogInfo(CST816S_EMU_LOG_PREFIX \"Event: X=%03u Y=%03u\\r\\n\", x, y);          conf-&gt;event.x = x;          conf-&gt;event.y = y;          conf-&gt;event_time = SysTick_GetCurrentTick();          conf-&gt;event_new = 1;          return STATUS_OK;       }        return STATUS_BUSY;    }     return STATUS_ERROR; }  void cst816s_emu_Routine(cst816s_emu_touch_t *conf) {    if (conf-&gt;inited)    {       if (conf-&gt;event_new)       {          target_ResetPin(conf-&gt;int_port, conf-&gt;int_pin);          if (SysTick_GetCurrentTick() - conf-&gt;event_time) \/\/ 1ms          {             target_SetPin(conf-&gt;int_port, conf-&gt;int_pin);             conf-&gt;event_new = 0;          }       }    } }  void cst816s_emu_Reg(cst816s_emu_touch_t *conf, uint8_t data) {    if (conf-&gt;inited)    {       conf-&gt;reg_addr = data;    } }  void cst816s_emu_Write(cst816s_emu_touch_t *conf, uint8_t data) {    if (conf-&gt;inited)    {       \/\/ TODO: skip all    } }  void cst816s_emu_Read(cst816s_emu_touch_t *conf, uint8_t *data) {    if (conf-&gt;inited)    {       switch (conf-&gt;reg_addr)       {          case 0xa7:             *data = CST816S_EMU_CHIP_ID;          break;           case 0xa8:             *data = CST816S_EMU_PROJECT_ID;          break;           case 0xa9:             *data = CST816S_EMU_FIRMWARE_VER;          break;           case 0x01:             \/\/ gesture             *data = CST816S_GESTURE_NONE;          break;           case 0x02:             \/\/ points             *data = 0x01;          break;           case 0x03:             \/\/ event type [7:6] + msb 4bit x             *data = 0 | ((conf-&gt;event.x &gt;&gt; 8) &amp; 0xF);          break;           case 0x04:             \/\/ lsb x             *data = (conf-&gt;event.x &amp; 0xFF);          break;           case 0x05:             \/\/ msb 4bit y             *data = ((conf-&gt;event.y &gt;&gt; 8) &amp; 0xF);          break;           case 0x06:             \/\/ lsb y             *data = (conf-&gt;event.y &amp; 0xFF);          break;           default:             *data = 0xFF;          break;       }        conf-&gt;reg_addr++;    } }  void cst816s_emu_Done(cst816s_emu_touch_t *conf) {    if (conf-&gt;inited)    {       conf-&gt;reg_addr = 0x00;    } } <\/code><\/pre>\n<\/div>\n<\/details>\n<h2>stm32g4xx_init<\/h2>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 I2C \u043f\u0435\u0440\u0438\u0444\u0435\u0440\u0438\u0438 \u043d\u0430 LL, \u0432\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043d\u0435 \u0441\u0442\u043e\u043b\u044c \u0432\u0430\u0436\u043d\u043e:<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>void SysInit_I2C(void) {    \/\/ I2C1: SCL (PA15), SDA (PB7) - Slave    LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_15, LL_GPIO_MODE_ALTERNATE);    LL_GPIO_SetAFPin_8_15(GPIOA, LL_GPIO_PIN_15, LL_GPIO_AF_4);    LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_15, LL_GPIO_OUTPUT_OPENDRAIN);    LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_15, LL_GPIO_SPEED_FREQ_HIGH);     LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_7, LL_GPIO_MODE_ALTERNATE);    LL_GPIO_SetAFPin_0_7(GPIOB, LL_GPIO_PIN_7, LL_GPIO_AF_4);    LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_7, LL_GPIO_OUTPUT_OPENDRAIN);    LL_GPIO_SetPinSpeed(GPIOB, LL_GPIO_PIN_7, LL_GPIO_SPEED_FREQ_HIGH);     LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);     LL_I2C_InitTypeDef I2C_InitStruct;    I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;    I2C_InitStruct.Timing = 0x00E057FD; \/\/ 400kHz    \/\/I2C_InitStruct.Timing = 0x20B0D9FF; \/\/ 100kHz    I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;    I2C_InitStruct.DigitalFilter = 2;    I2C_InitStruct.OwnAddress1 = 0;    I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;    I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;    LL_I2C_Init(I2C1, &amp;I2C_InitStruct);     LL_I2C_EnableAutoEndMode(I2C1);    LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);    LL_I2C_DisableOwnAddress2(I2C1); \/\/ TODO: ...    LL_I2C_DisableGeneralCall(I2C1);    LL_I2C_EnableClockStretching(I2C1);     NVIC_SetPriority(I2C1_EV_IRQn, 0);    NVIC_EnableIRQ(I2C1_EV_IRQn);    NVIC_SetPriority(I2C1_ER_IRQn, 0);    NVIC_EnableIRQ(I2C1_ER_IRQn);     \/\/ I2C2: SCL (PA9), SDA (PA8) - Master    LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_8, LL_GPIO_MODE_ALTERNATE);    LL_GPIO_SetAFPin_8_15(GPIOA, LL_GPIO_PIN_8, LL_GPIO_AF_4);    LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_8, LL_GPIO_OUTPUT_OPENDRAIN);    LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_8, LL_GPIO_SPEED_FREQ_HIGH);     LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_9, LL_GPIO_MODE_ALTERNATE);    LL_GPIO_SetAFPin_8_15(GPIOA, LL_GPIO_PIN_9, LL_GPIO_AF_4);    LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_9, LL_GPIO_OUTPUT_OPENDRAIN);    LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_9, LL_GPIO_SPEED_FREQ_HIGH);     LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C2);     I2C_InitStruct.OwnAddress1 = 0;    LL_I2C_Init(I2C2, &amp;I2C_InitStruct);     LL_I2C_EnableAutoEndMode(I2C2);    LL_I2C_SetOwnAddress2(I2C2, 0, LL_I2C_OWNADDRESS2_NOMASK);    LL_I2C_DisableOwnAddress2(I2C2);    LL_I2C_DisableGeneralCall(I2C2);    LL_I2C_EnableClockStretching(I2C2); }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0418\u0437 \u0432\u0430\u0436\u043d\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432 \u0437\u0434\u0435\u0441\u044c:<\/p>\n<ul>\n<li>\n<p>\u041e\u0431\u0430 I2C \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043a\u0430\u043a \u043c\u0430\u0441\u0442\u0435\u0440\u044b<\/p>\n<\/li>\n<li>\n<p><strong>LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK)<\/strong> \u2014 \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043c\u0430\u0441\u043a\u0443 \u0434\u043b\u044f I2C1, \u0447\u0442\u043e\u0431\u044b i2c_slave \u043c\u043e\u0433 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u043d\u0430 \u043b\u044e\u0431\u043e\u0439 \u0430\u0434\u0440\u0435\u0441, \u043d\u043e \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0441\u0442\u043e\u0438\u0442 \u043f\u0435\u0440\u0435\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0440\u043e\u043a\u0443<\/p>\n<\/li>\n<li>\n<p><strong>I2C1<\/strong> \u043f\u043e\u0441\u043b\u0435 \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0434\u0430\u043b\u044c\u0448\u0435 \u0432 \u0440\u0435\u0436\u0438\u043c slave, \u0438 \u0442\u0430\u043c \u0436\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u043e\u0442 \u043d\u0435\u0433\u043e (\u044d\u0442\u043e \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043a\u043e\u0433\u0434\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0443\u0436\u043d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u0430\u0441\u0442\u0435\u0440 FPD \u043c\u0438\u043a\u0440\u043e\u0441\u0445\u0435\u043c\u0443, \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u044f \u043f\u0440\u043e\u0431\u0440\u043e\u0441 I2C \u043f\u043e\u0432\u0435\u0440\u0445 FPD, \u0430 \u043f\u043e\u0442\u043e\u043c \u0443\u0436\u0435 \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u0436\u0435 I2C \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u043a\u0430\u043a \u0432\u0435\u0434\u043e\u043c\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e)<\/p>\n<\/li>\n<li>\n<p><strong>I2C2 <\/strong>\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432\u043e\u043e\u0431\u0449\u0435 \u0431\u0435\u0437 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0439 (\u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u0439 \u0434\u0440\u0430\u0439\u0432\u0435\u0440)<\/p>\n<\/li>\n<\/ul>\n<h2>stm32g4xx_it<\/h2>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u044b\u0437\u043e\u0432\u0430 \u043a\u043e\u043b\u0431\u0435\u043a\u043e\u0432 \u0434\u043b\u044f I2C1:<\/p>\n<pre><code>#include \"i2c_slave.h\" extern i2c_slave_t i2cs;  void I2C1_EV_IRQHandler(void) {    if (LL_I2C_IsActiveFlag_ADDR(i2cs.i2c))    {       LL_I2C_ClearFlag_ADDR(i2cs.i2c);       i2cSlave_IrqAddrSet(&amp;i2cs, (LL_I2C_GetAddressMatchCode(i2cs.i2c) &gt;&gt; 1));    }    else if (LL_I2C_IsActiveFlag_NACK(i2cs.i2c))    {       LL_I2C_ClearFlag_NACK(i2cs.i2c);       i2cSlave_IrqNack(&amp;i2cs);    }    else if (LL_I2C_IsActiveFlag_TXIS(i2cs.i2c))    {       i2cSlave_IrqTransmit(&amp;i2cs);    }    else if (LL_I2C_IsActiveFlag_RXNE(i2cs.i2c))    {       i2cSlave_IrqRecive(&amp;i2cs);    }    else if (LL_I2C_IsActiveFlag_STOP(i2cs.i2c))    {       LL_I2C_ClearFlag_STOP(i2cs.i2c);       if (!LL_I2C_IsActiveFlag_TXE(i2cs.i2c))       {          LL_I2C_ClearFlag_TXE(i2cs.i2c);       }        i2cSlave_IrqComplete(&amp;i2cs);    } }  void I2C1_ER_IRQHandler(void) {    i2cSlave_IrqError(&amp;i2cs); }<\/code><\/pre>\n<p>\u0413\u043b\u0430\u0432\u043d\u043e\u0435, \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c \u0444\u043b\u0430\u0433\u0438 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c. \ud83d\ude42<\/p>\n<h2>main<\/h2>\n<p>\u041d\u0443 \u0438, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0432\u043e\u0442 \u0442\u0430\u043a \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u044d\u0442\u043e \u0432\u0441\u0451 \u0434\u043e\u0431\u0440\u043e:<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>#include \"main.h\" #include \"stm32g4xx_init.h\"  #include \"cst816s.h\" cst816s_touch_t touch; volatile uint8_t touch_int = 0;  #include \"i2c_slave.h\" i2c_slave_t i2cs;  #include \"cst816s_emu.h\" cst816s_emu_touch_t touch_emu;  int main(void) {    SysInit_Clock();    SysTick_Config(SystemCoreClock \/ 1000U); \/\/ 1ms \/\/ No OS    SysInit_GPIO();    SysInit_I2C();     SysView_Init();    SysView_PrintInfo();     cst816s_Init(&amp;touch, I2C2, CST816S_DEFAULT_ADDRESS);     i2cSlave_Init(&amp;i2cs, I2C1);    i2cSlave_Enable(&amp;i2cs);     touch_emu.int_port = GPIOB;    touch_emu.int_pin = LL_GPIO_PIN_5;    cst816s_emu_Init(&amp;touch_emu, I2C1, CST816S_EMU_DEFAULT_ADDRESS);    i2cSlave_Register(&amp;i2cs, CST816S_EMU_DEFAULT_ADDRESS, &amp;touch_emu,                      &amp;cst816s_emu_Reg,                      &amp;cst816s_emu_Write,                      &amp;cst816s_emu_Read,                      &amp;cst816s_emu_Done);     for (;;)    {       cst816s_emu_Routine(&amp;touch_emu);       if (touch_int)       {          touch_int = 0;          cst816s_ReadEvent(&amp;touch);          cst816s_emu_NewEvent(&amp;touch_emu, touch.event.x, touch.event.y);       }    } }<\/code><\/pre>\n<\/div>\n<\/details>\n<h2>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430<\/h2>\n<p>\u0411\u0430\u0445\u0430\u0435\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430 \u0441\u0442\u043e\u043b\u0435 \u0441\u0442\u0435\u043d\u0434 \u043f\u043e \u0431\u043b\u043e\u043a-\u0441\u0445\u0435\u043c\u0435:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a6e\/213\/f89\/a6e213f891ff3d80be512734df5efe81.jpg\" alt=\"\u0415\u0449\u0451 \u0438 \u0437\u0430\u043f\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u043e\u0442 J-Link \u0432\u0441\u0451.\" title=\"\u0415\u0449\u0451 \u0438 \u0437\u0430\u043f\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u043e\u0442 J-Link \u0432\u0441\u0451.\" width=\"1152\" height=\"1479\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/a6e\/213\/f89\/a6e213f891ff3d80be512734df5efe81.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a6e\/213\/f89\/a6e213f891ff3d80be512734df5efe81.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0415\u0449\u0451 \u0438 \u0437\u0430\u043f\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u043e\u0442 J-Link \u0432\u0441\u0451.<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u043f\u0435\u0440\u0432\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u043a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a (\u0432\u044b\u0448\u0435 \u043f\u0440\u0438\u0432\u0451\u043b \u0443\u0436\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438):<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/027\/6f8\/8a7\/0276f88a73d01689f0a378e907671340.jpg\" alt=\"\u041a\u043e\u0433\u0434\u0430 \u043c\u0430\u0441\u0442\u0435\u0440-\u043f\u043b\u0430\u0442\u0430 \u043f\u0440\u043e\u0431\u0443\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u043c\" title=\"\u041a\u043e\u0433\u0434\u0430 \u043c\u0430\u0441\u0442\u0435\u0440-\u043f\u043b\u0430\u0442\u0430 \u043f\u0440\u043e\u0431\u0443\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u043c\" width=\"800\" height=\"450\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/027\/6f8\/8a7\/0276f88a73d01689f0a378e907671340.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/027\/6f8\/8a7\/0276f88a73d01689f0a378e907671340.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041a\u043e\u0433\u0434\u0430 \u043c\u0430\u0441\u0442\u0435\u0440-\u043f\u043b\u0430\u0442\u0430 \u043f\u0440\u043e\u0431\u0443\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u043c<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u043e \u0441\u043f\u0443\u0441\u0442\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/27a\/783\/b69\/27a783b698c6328b283e488952a911df.gif\" alt=\"\u0412\u043e\u0442 \u043c\u044b \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0442\u0440\u043e\u043b\u043b\u0435\u0439\u0431\u0443\u0441 \u0438\u0437 \u0431\u0443\u0445\u0430\u043d\u043a\u0438... \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442!\" title=\"\u0412\u043e\u0442 \u043c\u044b \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0442\u0440\u043e\u043b\u043b\u0435\u0439\u0431\u0443\u0441 \u0438\u0437 \u0431\u0443\u0445\u0430\u043d\u043a\u0438... \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442!\" width=\"400\" height=\"711\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/27a\/783\/b69\/27a783b698c6328b283e488952a911df.gif 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/27a\/783\/b69\/27a783b698c6328b283e488952a911df.gif 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0412\u043e\u0442 \u043c\u044b \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0442\u0440\u043e\u043b\u043b\u0435\u0439\u0431\u0443\u0441 \u0438\u0437 \u0431\u0443\u0445\u0430\u043d\u043a\u0438&#8230; \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442!<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u043e\u0442 \u0442\u0430\u043a \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/cab\/1a9\/ad7\/cab1a9ad7e8357660397646cfff10e72.gif\" alt=\"RTT\" title=\"RTT\" width=\"800\" height=\"1208\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/cab\/1a9\/ad7\/cab1a9ad7e8357660397646cfff10e72.gif 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/cab\/1a9\/ad7\/cab1a9ad7e8357660397646cfff10e72.gif 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>RTT<\/figcaption><\/div>\n<\/figure>\n<h2>sysview_init (\u0431\u043e\u043d\u0443\u0441)<\/h2>\n<p>\u0427\u0438\u0441\u0442\u043e \u0434\u043e\u043f\u043e\u043c, \u0432\u0434\u0440\u0443\u0433 \u043a\u043e\u043c\u0443 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u2014 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043d\u0430\u0434\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430\u0434 Segger RTT, \u0447\u0442\u043e\u0431\u044b \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u043d\u0438\u0442\u0438\u0442\u044c \u0438 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0446\u0432\u0435\u0442\u043d\u044b\u0435 \u0431\u0443\u043a\u043e\u0432\u043a\u0438 \u0432 RTT, \u043a\u0430\u043a \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u0438 \u044d\u043a\u0440\u0430\u043d\u0430 \u0432\u044b\u0448\u0435:<\/p>\n<p><strong>sysview_init.h<\/strong><\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>#ifndef _SYSTEMVIEW_INIT_H_ #define _SYSTEMVIEW_INIT_H_  #include \"stm32g4xx.h\" #include &lt;stdio.h&gt; #include \"main.h\"  #define SYSVIEW_APP_NAME                     \"LLSDK App\" #define SYSVIEW_DEVICE_NAME                  \"STM32G431CBU6\" #define SEGGER_SYSVIEW_EXCLUDE_PRINTF        1 #define SEGGER_RTT_MODE_DEFAULT              SEGGER_RTT_MODE_NO_BLOCK_SKIP #define SYSVIEW_NUM_TASKS                    16 \/\/ No OS  #ifndef USE_CYCCNT_TIMESTAMP #define USE_CYCCNT_TIMESTAMP                 1 #endif  #ifndef ENABLE_DWT_CYCCNT #define ENABLE_DWT_CYCCNT                    (USE_CYCCNT_TIMESTAMP &amp; SEGGER_SYSVIEW_POST_MORTEM_MODE) #endif  #define DWT_CTRL                             (*(volatile unsigned long*) (0xE0001000uL)) #define NOCYCCNT_BIT                         (1uL &lt;&lt; 25) #define CYCCNTENA_BIT                        (1uL &lt;&lt; 0)  #if(LIB_COMMON_SYSVIEW)  #include \"SEGGER_SYSVIEW.h\" #include \"SEGGER_SYSVIEW_Conf.h\" #include \"SEGGER_RTT.h\" #include \"SEGGER_RTT_Conf.h\"  #define SysView_ExecuteTask(t)               SEGGER_SYSVIEW_OnTaskStartExec((U32)t); \\                                              t(); \\                                              SEGGER_SYSVIEW_OnTaskStopReady((U32)t, 0);  #define SysView_LogInfo                      SEGGER_SYSVIEW_PrintfTarget #define SysView_LogWarning                   SEGGER_SYSVIEW_WarnfTarget #define SysView_LogError                     SEGGER_SYSVIEW_ErrorfTarget #define SysView_LogSuccess                   SEGGER_SYSVIEW_PrintfTarget #define SysView_EnterISR                     SEGGER_SYSVIEW_RecordEnterISR #define SysView_ExitISR                      SEGGER_SYSVIEW_RecordExitISR  #elif(LIB_COMMON_RTT)  #include \"SEGGER_RTT.h\" #include \"SEGGER_RTT_Conf.h\"  #define SysView_ExecuteTask(t)               t(); #define SysView_LogInfo(FORMAT, ...)         SEGGER_RTT_printf(0, FORMAT, ##__VA_ARGS__) #define SysView_LogWarning(FORMAT, ...)      SEGGER_RTT_printf(0, RTT_CTRL_TEXT_BRIGHT_YELLOW FORMAT RTT_CTRL_RESET, ##__VA_ARGS__) #define SysView_LogError(FORMAT, ...)        SEGGER_RTT_printf(0, RTT_CTRL_TEXT_BRIGHT_RED FORMAT RTT_CTRL_RESET, ##__VA_ARGS__) #define SysView_LogSuccess(FORMAT, ...)      SEGGER_RTT_printf(0, RTT_CTRL_TEXT_BRIGHT_GREEN FORMAT RTT_CTRL_RESET, ##__VA_ARGS__) #define SysView_EnterISR() #define SysView_ExitISR()  #else  #define SysView_ExecuteTask(t)               t(); #define SysView_LogInfo(...) #define SysView_LogWarning(...) #define SysView_LogError(...) #define SysView_LogSuccess(...) #define SysView_EnterISR() #define SysView_ExitISR()  #endif  void SysView_Init(void); void SysView_PrintInfo(void); void SysView_AddTask(void* pTask, const char* sName, uint32_t Prio); char SysView_WaitForInputChar(void);  #endif \/\/ _SYSTEMVIEW_INIT_H_<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>sysview_init.c<\/strong><\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>#include \"sysview_init.h\" #include \"build_info.h\"  #if(LIB_COMMON_SYSVIEW) static void _cb_SendTaskList(void); static void _cb_SendSystemDesc(void);  static const SEGGER_SYSVIEW_OS_API SysView_API = { NULL, _cb_SendTaskList }; static SEGGER_SYSVIEW_TASKINFO SysView_TasksInfo[SYSVIEW_NUM_TASKS]; static uint32_t SysView_TasksNum = 0;  static void _cb_SendSystemDesc(void) {    SEGGER_SYSVIEW_SendSysDesc(\"N=\"SYSVIEW_APP_NAME\",D=\"SYSVIEW_DEVICE_NAME);    SEGGER_SYSVIEW_SendSysDesc(    \/\/\",I#15=SysTick\"    ); }  static void _cb_SendTaskList(void) {    for (uint32_t n = 0; n &lt; SysView_TasksNum; n++)       SEGGER_SYSVIEW_SendTaskInfo(&amp;SysView_TasksInfo[n]); }  void SysView_AddTask(void* pTask, const char* sName, uint32_t Prio) {    uint32_t n;    SEGGER_SYSVIEW_OnTaskCreate((U32)pTask);     if (SysView_TasksNum &gt; SYSVIEW_NUM_TASKS)       return;     n = SysView_TasksNum;    SysView_TasksNum++;     SysView_TasksInfo[n].TaskID      = (U32)pTask;    SysView_TasksInfo[n].sName       = sName;    SysView_TasksInfo[n].Prio        = Prio;    SysView_TasksInfo[n].StackBase   = 0;    SysView_TasksInfo[n].StackSize   = 0; } #else void SysView_AddTask(void* pTask, const char* sName, uint32_t Prio) { } #endif \/\/ LIB_COMMON_SYSVIEW  void SysView_Init(void) { #if(LIB_COMMON_SYSVIEW) #if(SEGGER_SYSVIEW_CORE == SEGGER_SYSVIEW_CORE_CM3)    if (((DWT_CTRL &amp; NOCYCCNT_BIT) == 0) &amp;&amp; ((DWT_CTRL &amp; CYCCNTENA_BIT) == 0))    {       DWT_CTRL |= CYCCNTENA_BIT;    } #endif \/\/ SEGGER_SYSVIEW_CORE     SEGGER_SYSVIEW_Init(SystemCoreClock, SystemCoreClock, &amp;SysView_API, _cb_SendSystemDesc);    SEGGER_SYSVIEW_SetRAMBase(SYSVIEW_BASE_RAM_ADDR); #elif(LIB_COMMON_RTT)    SEGGER_RTT_Init(); #endif \/\/ LIB_COMMON_SYSVIEW }  #if(LIB_COMMON_SYSVIEW || LIB_COMMON_RTT) char SysView_WaitForInputChar(void) {    while(SEGGER_RTT_HasKey() == 0) ;    return SEGGER_RTT_GetKey(); } #else char SysView_WaitForInputChar(void) {    return 0x00; } #endif  void SysView_PrintInfo(void) {    SysView_LogInfo(RTT_CTRL_CLEAR);    SysView_LogInfo(\"Compiled:    %s\\r\\n\", COMPILE_DATE);    SysView_LogInfo(\"Compiler:    %s\\r\\n\", COMPILER_VERSION); #ifdef xPortSysTickHandler \/\/ FreeRTOS    SysView_LogInfo(\"FreeRTOS:    %s\\r\\n\", tskKERNEL_VERSION_NUMBER); #endif    SysView_LogInfo(\"Device:      %s\\r\\n\", SYSVIEW_DEVICE_NAME);    SysView_LogInfo(\"App Name:    %s\\r\\n\", SYSVIEW_APP_NAME);    SysView_LogInfo(\"Core Clock:  %u Hz (%u MHz)\\r\\n\\r\\n\", SystemCoreClock, SystemCoreClock \/ 1000000); }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u043d\u0430 \u043a\u0430\u043d\u0430\u043b <span class=\"habrahidden\">(\u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0435\u0442)<\/span>, \u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u043e\u0431\u0441\u0438\u0440\u0430\u0439\u0442\u0435 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0445. :3<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/933604\/\"> https:\/\/habr.com\/ru\/articles\/933604\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u043b\u043e\u0441\u044c \u043c\u043d\u0435 <s>\u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/s> \u043f\u043e \u043f\u0440\u0438\u043a\u043e\u043b\u0443 \u0441\u0434\u0435\u043b\u0430\u0442\u044c i2c slave (\u0432\u0435\u0434\u043e\u043c\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430), \u043d\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u044e \u043e\u0434\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 eeprom), \u0430 \u0441\u0440\u0430\u0437\u0443 \u044d\u0434\u0430\u043a\u043e\u0433\u043e \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0441, \u0435\u0441\u043b\u0438 \u043c\u043e\u0436\u043d\u043e \u044d\u0442\u043e \u0442\u0430\u043a \u043d\u0430\u0437\u0432\u0430\u0442\u044c, API, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0443\u0436\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0430\u0434\u0440\u0435\u0441\u0430.<\/p>\n<p>\u041d\u0430 \u0442\u0435\u043c\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0435\u0434\u043e\u043c\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u043d\u0430 STM32 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c LL \u044f \u043a\u0430\u043a-\u0442\u043e \u043d\u0435 \u043e\u0441\u043e\u0431\u043e \u043c\u043d\u043e\u0433\u043e \u0438\u043d\u0444\u044b \u043d\u0430\u0440\u044b\u043b, \u0432 \u0438\u0442\u043e\u0433\u0435 \u043d\u0430\u043a\u043e\u0441\u0442\u044b\u043b\u0438\u043b, \u043a\u0430\u043a \u0441\u0430\u043c \u043f\u043e\u043d\u044f\u043b \ud83d\ude00 \u0422\u0435\u0441\u0442 \u043e\u0442\u0432\u0451\u0440\u0442\u043a\u043e\u0439 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442, \u0445\u043e\u0442\u044f \u043f\u0435\u0440\u0432\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u043e\u0433\u0434\u0430 \u043f\u0440\u044f\u043c \u0437\u0430\u043b\u0438\u043f\u0430\u043b\u0438 \u043d\u0430\u043c\u0435\u0440\u0442\u0432\u043e.<\/p>\n<p>\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u0433\u043b\u0443\u0431\u043e\u043a\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u044b, \u0441\u0430\u043c\u0443 \u0440\u0430\u0431\u043e\u0442\u0443 \u0448\u0438\u043d\u044b, \u043f\u0440\u043e\u0447\u0435\u0435, \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0431\u0440\u0430 \u043d\u0430\u0432\u0430\u043b\u043e\u043c. \u041f\u0440\u043e\u0441\u0442\u043e \u043e\u043a\u0443\u043d\u0451\u043c\u0441\u044f \u0432 <s>\u0434\u0438\u043f \u0434\u0430\u0440\u043a \u0444\u044d\u043d\u0442\u0435\u0437\u0438<\/s> \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0435\u0433\u043e \u0442\u0430\u0447\u0430 <strong>cst816s.<\/strong><\/p>\n<p>\u0414\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u0441\u0442\u0435\u043d\u0434:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0411\u043b\u043e\u043a-\u0441\u0445\u0435\u043c\u0430 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043d\u0430 \u0441\u0442\u043e\u043b\u0435 \u043c\u0430\u043a\u0435\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043c\u0430\u0441\u0442\u0435\u0440-\u043f\u043b\u0430\u0442\u044b \u0437\u0434\u0435\u0441\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u0442, \u0435\u0441\u043b\u0438 \u043e\u0447\u0435\u043d\u044c \u043d\u0430\u0434\u043e, \u0442\u043e \u043c\u043e\u0433\u0443 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0434\u0440\u0430\u0439\u0432\u0435\u0440 LCD \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 LVGL.<\/em><\/p>\n<h2>I2C Slave<\/h2>\n<p>\u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0431\u0430\u0437\u044b. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442 \u2014 \u044d\u0442\u043e <strong>i2c_slave<\/strong> \u0444\u0430\u0439\u043b\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0441\u0430\u043c\u044b\u0439 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u0434 \u043f\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0439 \u0438 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0435\u0434\u043e\u043c\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432. \u042d\u0442\u043e\u0442 \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442 \u0443\u043c\u0435\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u043c\u0430\u0441\u0442\u0435\u0440\u0443 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e, \u0434\u0430\u0436\u0435 \u0431\u0435\u0437 \u0435\u0434\u0438\u043d\u043e\u0439 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432, \u0449\u0435\u0434\u0440\u043e \u0432\u044b\u0432\u0430\u043b\u0438\u0432\u0430\u044f \u0432\u0441\u0451 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0435 \u0432 \u043b\u043e\u0433 (Segger RTT).<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e \u0432 \u0432\u0438\u0434\u0435 \u0431\u043b\u043e\u043a-\u0441\u0445\u0435\u043c\u044b, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<figure class=\"\">\n<div><figcaption>wtf<\/figcaption><\/div>\n<\/figure>\n<div class=\"floating-image\">\n<p><strong>i2c_slave.h<\/strong><\/p>\n<\/div>\n<p>\u0412 \u0445\u0435\u0434\u0435\u0440\u0435 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0433\u043e. \u0414\u0435\u0444\u0430\u0439\u043d\u044b \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b:<\/p>\n<ul>\n<li>\n<p><strong>I2C_SLAVE_SLAVES_MAX <\/strong>\u2014 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432<\/p>\n<\/li>\n<li>\n<p> <strong>I2C_SLAVE_HW_DEBUG_LOG <\/strong>\u2014 \u043a\u0443\u0447\u0430 \u0434\u0435\u0431\u0430\u0433 \u0438\u043d\u0444\u044b \u0432 RTT<\/p>\n<\/li>\n<li>\n<p><strong>slave_instance_t <\/strong>\u2014 &#171;\u0441\u0441\u044b\u043b\u043a\u0430&#187; \u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430<\/p>\n<\/li>\n<li>\n<p><strong>i2c_slave_t <\/strong>\u2014 \u043a\u043e\u043d\u0444\u0438\u0433 \u0441\u0430\u043c\u043e\u0433\u043e i2c_slave (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e, \u043f\u043e\u0434 \u043a\u0430\u0436\u0434\u044b\u0439 \u0445\u0430\u0440\u0434\u0432\u0430\u0440\u043d\u044b\u0439 i2c)<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0435 \u0438\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n<ul>\n<li>\n<p><strong>i2cSlave_Init <\/strong>\u2014 \u0431\u0430\u0437\u043e\u0432\u0430\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/p>\n<\/li>\n<li>\n<p><strong>i2cSlave_Enable <\/strong>\\ <strong>i2cSlave_Disable <\/strong>\u2014 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 i2c_slave (\u043f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043d\u0435 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u0442\u0441\u044f, \u0442.\u043a. \u0431\u044b\u0432\u0430\u044e\u0442 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0431\u044b\u0442\u044c \u043d\u0430 \u0448\u0438\u043d\u0435 \u043c\u0430\u0441\u0442\u0435\u0440\u043e\u043c, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c \u0432\u0435\u0434\u043e\u043c\u043e\u0433\u043e)<\/p>\n<\/li>\n<li>\n<p><strong>i2cSlave_Register <\/strong>\u2014 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f (\u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0441\u044b\u043b\u043a\u0438) \u043d\u043e\u0432\u043e\u0433\u043e \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u043e\u043b\u0431\u0435\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0436\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u0437 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u0435\u0440\u0438\u0444\u0435\u0440\u0438\u0438 (\u0432 \u043c\u043e\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 i2c \u043d\u0430 LL \u0432 \u0440\u0435\u0436\u0438\u043c\u0430 \u043c\u0430\u0441\u0442\u0435\u0440\u0430 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f):<\/p>\n<ul>\n<li>\n<p><strong>i2cSlave_IrqAddrSet <\/strong>\u2014 \u043d\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0442 \u043c\u0430\u0441\u0442\u0435\u0440\u0430 \u0441 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u0432\u0435\u0434\u043e\u043c\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430<\/p>\n<\/li>\n<li>\n<p><strong>i2cSlave_IrqRecive <\/strong>\u2014 \u043f\u0440\u0438\u043d\u044f\u0442 \u0431\u0430\u0439\u0442<\/p>\n<\/li>\n<li>\n<p><strong>i2cSlave_IrqTransmit <\/strong>\u2014 \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d \u0431\u0430\u0439\u0442<\/p>\n<\/li>\n<li>\n<p><strong>i2cSlave_IrqNack <\/strong>\u2014 \u043f\u043e\u043b\u0443\u0447\u0435\u043d NACK<\/p>\n<\/li>\n<li>\n<p><strong>i2cSlave_IrqError <\/strong>\u2014 \u043e\u0448\u0438\u0431\u043a\u0430 \u043d\u0430 \u0448\u0438\u043d\u0435<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u0437 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0439, \u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0438\u0436\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>#ifndef _I2C_SLAVE_H_ #define _I2C_SLAVE_H_  \/* ----------------------------------------------------------------------------------------------------------------- \/\/ v0.10 - 2025.07.20: - \u041f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f  v0.11 - 2025.07.21: - \u041c\u0435\u043b\u043a\u0438\u0435 \u043f\u0440\u0430\u0432\u043a\u0438, \u0432\u0440\u043e\u0434\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442  \/\/ ----------------------------------------------------------------------------------------------------------------- *\/  #include \"main.h\"  #ifndef I2C_SLAVE_SLAVES_MAX #define I2C_SLAVE_SLAVES_MAX          20 #endif  #define I2C_SLAVE_LOG_PREFIX          \"[i2c_slv] \"  #ifndef I2C_SLAVE_HW_DEBUG_LOG #define I2C_SLAVE_HW_DEBUG_LOG        0 #endif  typedef struct __attribute__((__packed__)) {    uint8_t addr;    void *conf;    void (*freg)(void *, uint8_t);    void (*fwrite)(void *, uint8_t);    void (*fread)(void *, uint8_t *);    void (*fdone)(void *); } slave_instance_t;  typedef struct __attribute__((__packed__)) {    uint8_t inited;    uint8_t addr;    uint8_t reg;    uint8_t slave_num;    uint8_t slave_id;    void *i2c;    slave_instance_t slave[I2C_SLAVE_SLAVES_MAX]; } i2c_slave_t;  uint32_t i2cSlave_Init(i2c_slave_t *conf, void *hi2c); void i2cSlave_Enable(i2c_slave_t *conf); void i2cSlave_Disable(i2c_slave_t *conf); uint32_t i2cSlave_Register(i2c_slave_t *conf, uint8_t slave_addr, void *slave_conf, void *freg, void *fwrite, void *fread, void *fdone);  \/\/ Call in Interrupt uint32_t i2cSlave_IrqAddrSet(i2c_slave_t *conf, uint8_t addr); void i2cSlave_IrqRecive(i2c_slave_t *conf); void i2cSlave_IrqTransmit(i2c_slave_t *conf); void i2cSlave_IrqComplete(i2c_slave_t *conf); void i2cSlave_IrqNack(i2c_slave_t *conf); void i2cSlave_IrqError(i2c_slave_t *conf);  #endif \/\/ _I2C_SLAVE_H_<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>i2c_slave.c<\/strong><\/p>\n<p>\u0412 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0436\u0435 \u043e\u0441\u043e\u0431\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u043e\u0433\u043e, \u043d\u043e \u0435\u0441\u0442\u044c-\u0442\u0430\u043a\u0438 \u043f\u0430\u0440\u0430 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432:<\/p>\n<ul>\n<li>\n<p>i2c_slave \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u0432\u0441\u0435 \u0430\u0434\u0440\u0435\u0441\u0430, \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u044b\u0435 \u043c\u0430\u0441\u043a\u043e\u0439 (\u0430 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u0443 \u043c\u0430\u0441\u0442\u0435\u0440\u0430 \u043c\u043e\u0436\u0435\u0442 \u0441\u0431\u043e\u0438\u0442\u044c \u0438 &#171;\u0432\u0438\u0434\u0435\u0442\u044c&#187; \u043a\u0443\u0447\u0443 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u043d\u0430 \u0448\u0438\u043d\u0435), \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u044d\u0442\u043e \u0442\u0430\u043a:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u041c\u0430\u0441\u0442\u0435\u0440 \u0441\u043a\u0430\u043d\u0438\u0442 \u0448\u0438\u043d\u0443 \u0438 \u0432\u0438\u0434\u0438\u0442 \u0438\u043b\u043b\u044e\u0437\u0438\u044e \u0438\u0437\u043e\u0431\u0438\u043b\u0438\u044f \u0432\u0435\u0434\u043e\u043c\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u043e\u043b\u044c\u043a\u043e 0x15<\/figcaption><\/div>\n<\/figure>\n<\/li>\n<li>\n<p>\u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430, \u0430 \u043c\u0430\u0441\u0442\u0435\u0440 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0431\u0430\u0439\u0442, \u0442\u043e i2c_slave \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u043c\u0443 0xFF \u0432\u0441\u0435\u0433\u0434\u0430<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>#include \"i2c_slave.h\" #include &lt;string.h&gt;  uint32_t i2cSlave_Init(i2c_slave_t *conf, void *hi2c) {    conf-&gt;i2c = hi2c;    conf-&gt;inited = 1;    conf-&gt;slave_num = 0;    conf-&gt;slave_id = 0xff;    conf-&gt;reg = 0;     for (uint8_t i = 0; i &lt; I2C_SLAVE_SLAVES_MAX; i++)    {       conf-&gt;slave[i].addr = 0xff;    }     \/\/ TODO: \u043a\u0440\u0438\u0432\u043e\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435, \u043d\u043e \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0437\u0430\u0434\u0430\u0447 \u043f\u043e\u0439\u0434\u0451\u0442    SysView_LogSuccess(\"\\r\\n\" I2C_SLAVE_LOG_PREFIX \"Inited at I2C%u\\r\\n\", (hi2c == I2C1) ? 1 : 2);    return 0x00; }  void i2cSlave_Enable(i2c_slave_t *conf) {    if (conf-&gt;inited)    {       LL_I2C_SetOwnAddress1(conf-&gt;i2c, (0x01 &lt;&lt; 1), LL_I2C_OWNADDRESS1_7BIT);       LL_I2C_SetOwnAddress2(conf-&gt;i2c, (0x00 &lt;&lt; 1), LL_I2C_OWNADDRESS2_MASK07); \/\/ 7 bit only compare       LL_I2C_EnableOwnAddress1(conf-&gt;i2c);       LL_I2C_EnableOwnAddress2(conf-&gt;i2c);        LL_I2C_EnableIT_RX(conf-&gt;i2c);       LL_I2C_EnableIT_TX(conf-&gt;i2c);       LL_I2C_EnableIT_ADDR(conf-&gt;i2c);       LL_I2C_EnableIT_NACK(conf-&gt;i2c);       LL_I2C_EnableIT_ERR(conf-&gt;i2c);       LL_I2C_EnableIT_STOP(conf-&gt;i2c);        SysView_LogInfo(I2C_SLAVE_LOG_PREFIX \"Enabled\\r\\n\");    } }  void i2cSlave_Disable(i2c_slave_t *conf) {    if (conf-&gt;inited)    {       LL_I2C_DisableOwnAddress1(conf-&gt;i2c);       LL_I2C_DisableOwnAddress2(conf-&gt;i2c);        LL_I2C_DisableIT_RX(conf-&gt;i2c);       LL_I2C_DisableIT_TX(conf-&gt;i2c);       LL_I2C_DisableIT_ADDR(conf-&gt;i2c);       LL_I2C_DisableIT_NACK(conf-&gt;i2c);       LL_I2C_DisableIT_ERR(conf-&gt;i2c);       LL_I2C_DisableIT_STOP(conf-&gt;i2c);        conf-&gt;slave_id = 0xff;       conf-&gt;reg = 0;       SysView_LogInfo(I2C_SLAVE_LOG_PREFIX \"Disabled\\r\\n\");    } }  uint32_t i2cSlave_Register(i2c_slave_t *conf, uint8_t slave_addr, void *slave_conf, void *freg, void *fwrite, void *fread, void *fdone) {    if (conf-&gt;inited)    {       if (conf-&gt;slave_num &lt; (I2C_SLAVE_SLAVES_MAX - 1))       {          for (uint8_t i = 0; i &lt; conf-&gt;slave_num; i++)          {             if (conf-&gt;slave[i].addr == slave_addr)             {                SysView_LogWarning(I2C_SLAVE_LOG_PREFIX \"0x%x already registered at id = %u! Skip\\r\\n\", slave_addr, i);                return 0x01;             }          }           SysView_LogInfo(I2C_SLAVE_LOG_PREFIX \"Registered: addr = 0x%x, id = %u\\r\\n\", slave_addr, conf-&gt;slave_num);          conf-&gt;slave[conf-&gt;slave_num].addr = slave_addr;          conf-&gt;slave[conf-&gt;slave_num].conf = slave_conf;          conf-&gt;slave[conf-&gt;slave_num].freg = freg;          conf-&gt;slave[conf-&gt;slave_num].fwrite = fwrite;          conf-&gt;slave[conf-&gt;slave_num].fread = fread;          conf-&gt;slave[conf-&gt;slave_num].fdone = fdone;          conf-&gt;slave_num++;          return 0x00;       }    }     return 0x01; }  uint32_t i2cSlave_IrqAddrSet(i2c_slave_t *conf, uint8_t addr) {    if (conf-&gt;inited)    { #if (I2C_SLAVE_HW_DEBUG_LOG)       SysView_LogInfo(I2C_SLAVE_LOG_PREFIX \"Addr 0x%x: \", addr); #endif       conf-&gt;addr = addr;       conf-&gt;reg = 0;       conf-&gt;slave_id = 0xff;       for (uint8_t i = 0; i &lt; conf-&gt;slave_num; i++)       {          if (conf-&gt;slave[i].addr == conf-&gt;addr)          {             conf-&gt;slave_id = i; #if (I2C_SLAVE_HW_DEBUG_LOG)             SysView_LogInfo(\"id = 0x%x\\r\\n\", conf-&gt;slave_id); #endif             return 0x00;          }       }        if (conf-&gt;slave_id == 0xff)       { #if (I2C_SLAVE_HW_DEBUG_LOG)          SysView_LogWarning(\"not found\\r\\n\"); #endif       }    }     return 0x01; }  void i2cSlave_IrqRecive(i2c_slave_t *conf) {    if (conf-&gt;inited)    {       uint8_t data = LL_I2C_ReceiveData8(conf-&gt;i2c);       if (conf-&gt;slave_id != 0xff)       {          if (conf-&gt;reg == 0)          { #if (I2C_SLAVE_HW_DEBUG_LOG)             SysView_LogInfo(I2C_SLAVE_LOG_PREFIX \"Reg = 0x%x\\r\\n\", data); #endif             conf-&gt;reg = 1;             conf-&gt;slave[conf-&gt;slave_id].freg(conf-&gt;slave[conf-&gt;slave_id].conf, data);          }          else          { #if (I2C_SLAVE_HW_DEBUG_LOG)             SysView_LogInfo(I2C_SLAVE_LOG_PREFIX \"Write 0x%x\\r\\n\", data); #endif             conf-&gt;slave[conf-&gt;slave_id].fwrite(conf-&gt;slave[conf-&gt;slave_id].conf, data);          }       }       else       {          SysView_LogWarning(I2C_SLAVE_LOG_PREFIX \"Write skip 0x%x\\r\\n\", data);       }    } }  void i2cSlave_IrqTransmit(i2c_slave_t *conf) {    if (conf-&gt;inited)    {       if (conf-&gt;slave_id != 0xff)       {          static uint8_t data;          data = 0x00;          conf-&gt;slave[conf-&gt;slave_id].fread(conf-&gt;slave[conf-&gt;slave_id].conf, &amp;data); #if (I2C_SLAVE_HW_DEBUG_LOG)          SysView_LogInfo(I2C_SLAVE_LOG_PREFIX \"Read 0x%x\\r\\n\", data); #endif          LL_I2C_TransmitData8(conf-&gt;i2c, data);          return ;       }  #if (I2C_SLAVE_HW_DEBUG_LOG)       SysView_LogWarning(I2C_SLAVE_LOG_PREFIX \"Read skip\\r\\n\"); #endif       LL_I2C_TransmitData8(conf-&gt;i2c, 0xff);    } }  void i2cSlave_IrqComplete(i2c_slave_t *conf) {    if (conf-&gt;inited)    { #if (I2C_SLAVE_HW_DEBUG_LOG)       SysView_LogSuccess(I2C_SLAVE_LOG_PREFIX \"Complete\\r\\n\"); #endif       conf-&gt;addr = 0xff;       conf-&gt;reg = 0;       if (conf-&gt;slave_id != 0xff)       {          conf-&gt;slave[conf-&gt;slave_id].fdone(conf-&gt;slave[conf-&gt;slave_id].conf);       }        conf-&gt;slave_id = 0xff;    } }  void i2cSlave_IrqNack(i2c_slave_t *conf) {    if (conf-&gt;inited)    { #if (I2C_SLAVE_HW_DEBUG_LOG)<\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-473119","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/473119","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=473119"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/473119\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=473119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=473119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=473119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}