ADS1256_soft.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include "ADS1256_soft.h"
  2. #include "cmsis_os.h"
  3. #include "gpio.h"
  4. /**
  5. ******************************************************************************
  6. * @file ADS1256.c
  7. ******************************************************************************
  8. * @attention
  9. * ADS1256模块
  10. * +5V <------ 5.0V 5V供电
  11. * GND ------- GND 地
  12. * DRDY ------> PA11 准备就绪 低准备好 高未准备好
  13. * CS <------ PB12 SPI_CS 低有效,操作完拉高
  14. * DIN <------ PB15 SPI_MOSI
  15. * DOUT ------> PB14 SPI_MISO
  16. * SCLK <------ PB13 SPI时钟
  17. * GND ------- GND 地
  18. * PDWN <------ VDD 掉电控制 常高
  19. * RST <------ PA8 复位信号 常高,拉低再拉高生效复位
  20. *
  21. * ADS1256基本特性:
  22. * 1、模拟部分供电5V;
  23. * 2、SPI数字接口电平:3.3V
  24. * 3、PGA设置范围: 1、2、4、8、16、32、64、
  25. * 4、参考电压2.5V (推荐缺省的,外置的)
  26. * 5、输入电压范围:PGA = 1 时, 可输入正负5V
  27. * 6. 自动校准 (当设置了PGA,BUF使能、数据采样率时,会启动自校准)
  28. * 7. 输入的缓冲器可设置启用和关闭(一般选启用)
  29. * 外部晶振频率 = 7.68MHz,
  30. * 时钟频率 tCLK = 1/7.68M = 0.13uS
  31. * 输出数据周期 tDATA = 1 / 30K = 0.033mS (按30Ksps计算)
  32. * 对SPI的时钟速度要求: (ads1256.pdf page 6)
  33. * 最快 4个tCLK = 0.52uS
  34. * 最慢 10个tDATA = 0.3mS (按 30Ksps 计算)
  35. * SCL高电平和低电平持续时间最小 200ns
  36. * RREG, WREG, RDATA 命令之后,需要延迟 4 * tCLK = 0.52uS;
  37. * RDATAC, RESET, SYNC 命令之后,需要延迟 24 * tCLK = 3.12uS;
  38. * 实际测试,在3.3V上电后, 及时不做任何配置,ADS125的DRDY 口线即开始输出脉冲信号(2.6us高,33.4低,频率30KHz)
  39. ******************************************************************************
  40. */
  41. //extern SPI_HandleTypeDef ADS1256_SPI_HANDLE;
  42. // 软件SPI发送单字节(模式1,CPOL=0, CPHA=1)
  43. static void SoftSPI_WriteByte(uint8_t data) {
  44. for (uint8_t i = 0; i < 8; i++) {
  45. SOFT_SPI_SCK_LOW();
  46. // 设置MOSI
  47. if (data & 0x80) SOFT_SPI_MOSI_HIGH();
  48. else SOFT_SPI_MOSI_LOW();
  49. data <<= 1;
  50. for (uint8_t m = 0; m < 40; m++){} // ~400ns @80MHz
  51. // 产生时钟上升沿(从机采样)
  52. SOFT_SPI_SCK_HIGH();
  53. for (volatile uint8_t j = 0; j < 40; j++); // ~200ns @80MHz
  54. }
  55. SOFT_SPI_SCK_LOW(); // 保持空闲状态为低
  56. }
  57. // 软件SPI接收单字节
  58. static uint8_t SoftSPI_ReadByte(void) {
  59. uint8_t data = 0;
  60. for (uint8_t i = 0; i < 8; i++) {
  61. data <<= 1;
  62. SOFT_SPI_SCK_HIGH();
  63. // 插入小延时(确保数据稳定)
  64. for (volatile uint32_t j = 0; j < 40; j++);
  65. if (SOFT_SPI_MISO_READ()) data |= 0x01;
  66. SOFT_SPI_SCK_LOW();
  67. for (volatile uint32_t j = 0; j < 40; j++);
  68. }
  69. return data;
  70. }
  71. static void ADS1256_SendCommand(uint8_t cmd) {
  72. ADS1256_CS_LOW();
  73. for (uint8_t m = 0; m < 40; m++){} // ~400ns @80MHz
  74. // HAL_SPI_Transmit(&ADS1256_SPI_HANDLE, &cmd, 1, SPI_TIMEOUT);
  75. SoftSPI_WriteByte(cmd);
  76. for (uint8_t m = 0; m < 40; m++){} // ~400ns @80MHz
  77. ADS1256_CS_HIGH();
  78. }
  79. void ADS1256_WriteRegister(uint8_t reg, uint8_t value) {
  80. uint8_t tx[3];
  81. tx[0] = ADS1256_CMD_WREG | (reg & 0x0F);
  82. tx[1] = 0x00; // write 1 register
  83. tx[2] = value;
  84. ADS1256_CS_LOW();
  85. for (uint8_t m = 0; m < 40; m++){} // ~400ns @80MHz
  86. // HAL_SPI_Transmit(&ADS1256_SPI_HANDLE, tx, 3, SPI_TIMEOUT);
  87. for (uint8_t i = 0; i < 40; i++) SoftSPI_WriteByte(tx[i]);
  88. ADS1256_CS_HIGH();
  89. osDelay(2);
  90. }
  91. uint8_t ADS1256_ReadRegister(uint8_t reg) {
  92. uint8_t tx[2] = { ADS1256_CMD_RREG | (reg & 0x0F), 0x00 };
  93. uint8_t rx = 0;
  94. ADS1256_CS_LOW();
  95. for (uint8_t m = 0; m < 40; m++){} // ~400ns @80MHz
  96. // HAL_SPI_Transmit(&ADS1256_SPI_HANDLE, tx, 2, SPI_TIMEOUT);
  97. SoftSPI_WriteByte(tx[0]);
  98. SoftSPI_WriteByte(tx[1]);
  99. osDelay(2);
  100. // HAL_SPI_Receive(&ADS1256_SPI_HANDLE, &rx, 1, SPI_TIMEOUT);
  101. rx = SoftSPI_ReadByte();
  102. for (uint8_t m = 0; m < 40; m++){} // ~400ns @80MHz
  103. ADS1256_CS_HIGH();
  104. return rx;
  105. }
  106. bool ADS1256_ReadData(int32_t* out) { // 读取数据(需判断 DRDY 是否为低)
  107. uint8_t rx[3];
  108. if (HAL_GPIO_ReadPin(ADS1256_DRDY_GPIO_PORT, ADS1256_DRDY_PIN) != GPIO_PIN_RESET) {
  109. return false;
  110. }
  111. ADS1256_CS_LOW();
  112. // HAL_SPI_Receive(&ADS1256_SPI_HANDLE, rx, 3, SPI_TIMEOUT);
  113. rx[0] = SoftSPI_ReadByte();
  114. rx[1] = SoftSPI_ReadByte();
  115. rx[2] = SoftSPI_ReadByte();
  116. ADS1256_CS_HIGH();
  117. *out = ((int32_t)rx[0] << 16) | ((int32_t)rx[1] << 8) | rx[2];
  118. if (*out & 0x800000) *out |= 0xFF000000; // Sign extend if negative
  119. return true;
  120. }
  121. void ADS1256_Reset(void) { // 复位
  122. HAL_GPIO_WritePin(GPIOB, ADS_SYNC_PDWN_Pin, GPIO_PIN_RESET);
  123. osDelay(5);
  124. HAL_GPIO_WritePin(GPIOB, ADS_SYNC_PDWN_Pin, GPIO_PIN_SET);
  125. osDelay(5);
  126. ADS1256_RST_LOW();
  127. osDelay(5);
  128. ADS1256_RST_HIGH();
  129. osDelay(5);
  130. ADS1256_SendCommand(ADS1256_CMD_RESET);
  131. osDelay(5);
  132. }
  133. uint8_t ADS1256_ReadID(void) { // 读取芯片 ID(高 4 位) ID高4位应该是0x03
  134. ADS1256_SendCommand(ADS1256_CMD_SYNC);
  135. ADS1256_SendCommand(ADS1256_CMD_WAKEUP);
  136. osDelay(1);
  137. uint8_t status = ADS1256_ReadRegister(ADS1256_REG_STATUS);
  138. return (status >> 4) & 0x0F; // 屏蔽低4位
  139. }
  140. void ADS1256_SetChannel(uint8_t mux) { // 设置输入通道(MUX 寄存器值)
  141. ADS1256_WriteRegister(ADS1256_REG_MUX, mux);
  142. ADS1256_SendCommand(ADS1256_CMD_SYNC);
  143. ADS1256_SendCommand(ADS1256_CMD_WAKEUP);
  144. }
  145. void ADS1256_SetGain(ADS1256_Gain_t gain) { // 设置增益
  146. uint8_t adcon = ADS1256_ReadRegister(ADS1256_REG_ADCON);
  147. adcon &= 0xF8;
  148. adcon |= (gain & 0x07);
  149. ADS1256_WriteRegister(ADS1256_REG_ADCON, adcon);
  150. }
  151. void ADS1256_SetDataRate(ADS1256_DataRate_t dr) { // 设置采样率
  152. ADS1256_WriteRegister(ADS1256_REG_DRATE, (uint8_t)dr);
  153. }
  154. void ADS1256_StartConversion(void) { // 启动一次转换
  155. ADS1256_SendCommand(ADS1256_CMD_SYNC);
  156. ADS1256_SendCommand(ADS1256_CMD_WAKEUP);
  157. ADS1256_SendCommand(ADS1256_CMD_RDATA);
  158. }
  159. float ADS1256_ConvertToVoltage(int32_t raw, float vref, int gain) {
  160. return ((float)raw / 8388608.0f) * (vref / gain); // V = (raw / 2的23次方)* (vref / gain) 单位V
  161. }
  162. void ADS1256_SetClockSource(uint8_t useInternal) // CLK = 0:使用外部晶振 1:使用内部晶振
  163. {
  164. if (useInternal > 1) return;
  165. uint8_t status = ADS1256_ReadRegister(ADS1256_REG_STATUS);
  166. if (useInternal)
  167. status |= (1 << 2); // CLK = 1:使用内部晶振
  168. else
  169. status &= ~(1 << 2); // CLK = 0:使用外部晶振
  170. ADS1256_WriteRegister(ADS1256_REG_STATUS, status);
  171. }
  172. bool ADS1256_IsUsingExternalClock(void)
  173. {
  174. uint8_t status = ADS1256_ReadRegister(ADS1256_REG_STATUS);
  175. return (status & (1 << 3)) != 0; // CLKSTAT
  176. }
  177. void ADS1256_Init(void) { // 初始化 ADS1256
  178. // ADS1256_Reset();
  179. // osDelay(50);
  180. ADS1256_SetClockSource(0); // 0使用外部晶振 1内部晶振
  181. ADS1256_WriteRegister(ADS1256_REG_STATUS, 0x06); // 0x06 0000 0 110 自动校准开启(ACAL = 1), 输入缓冲器关闭(BUFEN = 0)
  182. ADS1256_WriteRegister(ADS1256_REG_ADCON, 0x20); // 0x20 时钟输出禁用(CLKOUT = 00), 增益为1倍(输入是几mV,增益增大至8)
  183. ADS1256_SetDataRate(ADS1256_DR_1000SPS); // ADS1256_DR_1000SPS
  184. ADS1256_SetChannel(ADS1256_MUX_AIN1_AINCOM); // AIN1 - AINCOM
  185. ADS1256_SendCommand(ADS1256_CMD_SELFCAL);// 启动自动增益和偏移校准 必须最后执行该指令
  186. }