My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

eeprom_BL24CXX.cpp 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. /********************************************************************************
  23. * @file eeprom_BL24CXX.cpp
  24. * @brief i2c EEPROM for Ender 3 v2 board (4.2.2)
  25. ********************************************************************************/
  26. #include "../../inc/MarlinConfig.h"
  27. #if ENABLED(IIC_BL24CXX_EEPROM)
  28. #include "eeprom_BL24CXX.h"
  29. #include "../../MarlinCore.h"
  30. #include <stdlib.h>
  31. /******************** IIC ********************/
  32. // 初始化IIC
  33. void IIC::init() {
  34. SET_OUTPUT(IIC_EEPROM_SDA);
  35. SET_OUTPUT(IIC_EEPROM_SCL);
  36. IIC_SCL_1();
  37. IIC_SDA_1();
  38. }
  39. // 产生IIC起始信号
  40. void IIC::start() {
  41. SDA_OUT(); // sda线输出
  42. IIC_SDA_1();
  43. IIC_SCL_1();
  44. delay_us(4);
  45. IIC_SDA_0(); // START:when CLK is high, DATA change form high to low
  46. delay_us(4);
  47. IIC_SCL_0(); // 钳住I2C总线,准备发送或接收数据
  48. }
  49. // 产生IIC停止信号
  50. void IIC::stop() {
  51. SDA_OUT(); // sda线输出
  52. IIC_SCL_0();
  53. IIC_SDA_0(); // STOP:when CLK is high DATA change form low to high
  54. delay_us(4);
  55. IIC_SCL_1();
  56. IIC_SDA_1(); // 发送I2C总线结束信号
  57. delay_us(4);
  58. }
  59. // 等待应答信号到来
  60. // 返回值:1,接收应答失败
  61. // 0,接收应答成功
  62. uint8_t IIC::wait_ack() {
  63. uint8_t ucErrTime=0;
  64. SDA_IN(); // SDA设置为输入
  65. IIC_SDA_1();delay_us(1);
  66. IIC_SCL_1();delay_us(1);
  67. while (READ_SDA()) {
  68. ucErrTime++;
  69. if (ucErrTime>250) {
  70. stop();
  71. return 1;
  72. }
  73. }
  74. IIC_SCL_0(); // 时钟输出0
  75. return 0;
  76. }
  77. // 产生ACK应答
  78. void IIC::ack() {
  79. IIC_SCL_0();
  80. SDA_OUT();
  81. IIC_SDA_0();
  82. delay_us(2);
  83. IIC_SCL_1();
  84. delay_us(2);
  85. IIC_SCL_0();
  86. }
  87. // 不产生ACK应答
  88. void IIC::nAck() {
  89. IIC_SCL_0();
  90. SDA_OUT();
  91. IIC_SDA_1();
  92. delay_us(2);
  93. IIC_SCL_1();
  94. delay_us(2);
  95. IIC_SCL_0();
  96. }
  97. // IIC发送一个字节
  98. // 返回从机有无应答
  99. // 1,有应答
  100. // 0,无应答
  101. void IIC::send_byte(uint8_t txd) {
  102. SDA_OUT();
  103. IIC_SCL_0(); // 拉低时钟开始数据传输
  104. LOOP_L_N(t, 8) {
  105. // IIC_SDA = (txd & 0x80) >> 7;
  106. if (txd & 0x80) IIC_SDA_1(); else IIC_SDA_0();
  107. txd <<= 1;
  108. delay_us(2); // 对TEA5767这三个延时都是必须的
  109. IIC_SCL_1();
  110. delay_us(2);
  111. IIC_SCL_0();
  112. delay_us(2);
  113. }
  114. }
  115. // 读1个字节,ack=1时,发送ACK,ack=0,发送nACK
  116. uint8_t IIC::read_byte(unsigned char ack_chr) {
  117. unsigned char receive = 0;
  118. SDA_IN(); // SDA设置为输入
  119. LOOP_L_N(i, 8) {
  120. IIC_SCL_0();
  121. delay_us(2);
  122. IIC_SCL_1();
  123. receive <<= 1;
  124. if (READ_SDA()) receive++;
  125. delay_us(1);
  126. }
  127. ack_chr ? ack() : nAck(); // 发送ACK / 发送nACK
  128. return receive;
  129. }
  130. /******************** EEPROM ********************/
  131. // 初始化IIC接口
  132. void BL24CXX::init() { IIC::init(); }
  133. // 在BL24CXX指定地址读出一个数据
  134. // ReadAddr:开始读数的地址
  135. // 返回值 :读到的数据
  136. uint8_t BL24CXX::readOneByte(uint16_t ReadAddr) {
  137. uint8_t temp = 0;
  138. IIC::start();
  139. if (EE_TYPE > BL24C16) {
  140. IIC::send_byte(0xA0); // 发送写命令
  141. IIC::wait_ack();
  142. IIC::send_byte(ReadAddr >> 8); // 发送高地址
  143. IIC::wait_ack();
  144. }
  145. else
  146. IIC::send_byte(0xA0 + ((ReadAddr >> 8) << 1)); // 发送器件地址0xA0,写数据
  147. IIC::wait_ack();
  148. IIC::send_byte(ReadAddr & 0xFF); // 发送低地址
  149. IIC::wait_ack();
  150. IIC::start();
  151. IIC::send_byte(0xA1); // 进入接收模式
  152. IIC::wait_ack();
  153. temp = IIC::read_byte(0);
  154. IIC::stop(); // 产生一个停止条件
  155. return temp;
  156. }
  157. // 在BL24CXX指定地址写入一个数据
  158. // WriteAddr :写入数据的目的地址
  159. // DataToWrite:要写入的数据
  160. void BL24CXX::writeOneByte(uint16_t WriteAddr, uint8_t DataToWrite) {
  161. IIC::start();
  162. if (EE_TYPE > BL24C16) {
  163. IIC::send_byte(0xA0); // 发送写命令
  164. IIC::wait_ack();
  165. IIC::send_byte(WriteAddr >> 8); // 发送高地址
  166. }
  167. else {
  168. IIC::send_byte(0xA0 + ((WriteAddr >> 8) << 1)); // 发送器件地址0xA0,写数据
  169. }
  170. IIC::wait_ack();
  171. IIC::send_byte(WriteAddr & 0xFF); // 发送低地址
  172. IIC::wait_ack();
  173. IIC::send_byte(DataToWrite); // 发送字节
  174. IIC::wait_ack();
  175. IIC::stop(); // 产生一个停止条件
  176. delay(10);
  177. }
  178. // 在BL24CXX里面的指定地址开始写入长度为Len的数据
  179. // 该函数用于写入16bit或者32bit的数据.
  180. // WriteAddr :开始写入的地址
  181. // DataToWrite:数据数组首地址
  182. // Len :要写入数据的长度2,4
  183. void BL24CXX::writeLenByte(uint16_t WriteAddr, uint32_t DataToWrite, uint8_t Len) {
  184. LOOP_L_N(t, Len)
  185. writeOneByte(WriteAddr + t, (DataToWrite >> (8 * t)) & 0xFF);
  186. }
  187. // 在BL24CXX里面的指定地址开始读出长度为Len的数据
  188. // 该函数用于读出16bit或者32bit的数据.
  189. // ReadAddr :开始读出的地址
  190. // 返回值 :数据
  191. // Len :要读出数据的长度2,4
  192. uint32_t BL24CXX::readLenByte(uint16_t ReadAddr, uint8_t Len) {
  193. uint32_t temp = 0;
  194. LOOP_L_N(t, Len) {
  195. temp <<= 8;
  196. temp += readOneByte(ReadAddr + Len - t - 1);
  197. }
  198. return temp;
  199. }
  200. // 检查BL24CXX是否正常
  201. // 这里用了24XX的最后一个地址(255)来存储标志字.
  202. // 如果用其他24C系列,这个地址要修改
  203. // 返回1:检测失败
  204. // 返回0:检测成功
  205. uint8_t BL24CXX::check() {
  206. uint8_t temp;
  207. temp = readOneByte(255); // 避免每次开机都写BL24CXX
  208. if (temp == 'U') return 0;
  209. else { // 排除第一次初始化的情况
  210. writeOneByte(255, 'U');
  211. temp = readOneByte(255);
  212. if (temp == 'U') return 0;
  213. }
  214. return 1;
  215. }
  216. // 在BL24CXX里面的指定地址开始读出指定个数的数据
  217. // ReadAddr :开始读出的地址 对24c02为0~255
  218. // pBuffer :数据数组首地址
  219. // NumToRead:要读出数据的个数
  220. void BL24CXX::read(uint16_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead) {
  221. while (NumToRead) {
  222. *pBuffer++ = readOneByte(ReadAddr++);
  223. NumToRead--;
  224. }
  225. }
  226. // 在BL24CXX里面的指定地址开始写入指定个数的数据
  227. // WriteAddr :开始写入的地址 对24c02为0~255
  228. // pBuffer :数据数组首地址
  229. // NumToWrite:要写入数据的个数
  230. void BL24CXX::write(uint16_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite) {
  231. while (NumToWrite--) {
  232. writeOneByte(WriteAddr, *pBuffer);
  233. WriteAddr++;
  234. pBuffer++;
  235. }
  236. }
  237. #endif // IIC_BL24CXX_EEPROM