ADS1256.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. #include "ADS1256.h"
  2. #include "cmsis_os.h"
  3. #include "printf.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. void ADS1256_SendCommand(uint8_t cmd) { // 发送单字节命令给ADS
  43. ADS1256_CS_LOW();
  44. for (volatile uint8_t i = 0; i < 5; i++) {} // ≈300~500ns 延迟
  45. HAL_SPI_Transmit(&ADS1256_SPI_HANDLE, &cmd, 1, SPI_TIMEOUT);
  46. for (volatile uint8_t i = 0; i < 5; i++) {} // ≈300~500ns 延迟
  47. ADS1256_CS_HIGH();
  48. }
  49. void ADS1256_WriteRegister(uint8_t reg, uint8_t value) {
  50. uint8_t tx[3] = {
  51. ADS1256_CMD_WREG | (reg & 0x0F),
  52. 0x00, // 写1个寄存器
  53. value
  54. };
  55. ADS1256_CS_LOW();
  56. for (volatile uint8_t i = 0; i < 5; i++) {}
  57. HAL_SPI_Transmit(&ADS1256_SPI_HANDLE, tx, 3, SPI_TIMEOUT);
  58. for (volatile uint8_t i = 0; i < 5; i++) {}
  59. ADS1256_CS_HIGH();
  60. }
  61. uint8_t ADS1256_ReadRegister(uint8_t reg) {
  62. uint8_t tx[2] = { ADS1256_CMD_RREG | (reg & 0x0F), 0x00 };
  63. uint8_t rx = 0;
  64. ADS1256_CS_LOW();
  65. for (volatile uint8_t i = 0; i < 5; i++) {}
  66. HAL_SPI_Transmit(&ADS1256_SPI_HANDLE, tx, 2, SPI_TIMEOUT);
  67. for (volatile uint8_t i = 0; i < 5; i++) {} // ≈读取前延迟
  68. HAL_SPI_Receive(&ADS1256_SPI_HANDLE, &rx, 1, SPI_TIMEOUT);
  69. for (volatile uint8_t i = 0; i < 5; i++) {}
  70. ADS1256_CS_HIGH();
  71. return rx;
  72. }
  73. void ADS1256_Reset(void) { // 复位
  74. ADS1256_RST_LOW();
  75. osDelay(1);
  76. ADS1256_RST_HIGH();
  77. osDelay(5);
  78. ADS1256_SendCommand(ADS1256_CMD_RESET); // 软件复位
  79. osDelay(5);
  80. }
  81. void ADS1256_SetChannel(uint8_t mux) { // 设置输入通道(MUX 寄存器值)
  82. ADS1256_WriteRegister(ADS1256_REG_MUX, mux);
  83. ADS1256_SendCommand(ADS1256_CMD_SYNC);
  84. ADS1256_SendCommand(ADS1256_CMD_WAKEUP);
  85. }
  86. void ADS1256_SetGain(ADS1256_Gain_t gain) { // 设置增益
  87. uint8_t adcon = ADS1256_ReadRegister(ADS1256_REG_ADCON);
  88. adcon &= 0xF8;
  89. adcon |= (gain & 0x07);
  90. ADS1256_WriteRegister(ADS1256_REG_ADCON, adcon);
  91. }
  92. void ADS1256_SetDataRate(ADS1256_DataRate_t dr) { // 设置采样率
  93. ADS1256_WriteRegister(ADS1256_REG_DRATE, (uint8_t)dr);
  94. }
  95. void ADS1256_StartConversion(void) { // 启动一次转换
  96. ADS1256_SendCommand(ADS1256_CMD_SYNC);
  97. ADS1256_SendCommand(ADS1256_CMD_WAKEUP);
  98. ADS1256_SendCommand(ADS1256_CMD_RDATA);
  99. }
  100. uint8_t ADS1256_ReadID(void) { // 读取芯片 ID(高 4 位) ID高4位应该是0x03
  101. ADS1256_SendCommand(ADS1256_CMD_SYNC);
  102. osDelay(1); // 延迟 ≥6us,这里用1ms最保险,兼容RTOS调度延迟
  103. ADS1256_SendCommand(ADS1256_CMD_WAKEUP);
  104. for (volatile uint8_t i = 0; i < 5; i++) {} // 补一点 CS 往后延
  105. uint8_t status = ADS1256_ReadRegister(ADS1256_REG_STATUS);
  106. return (status >> 4) & 0x0F;
  107. }
  108. bool ADS1256_ReadData(int32_t* out) { // 读取数据(需判断 DRDY 是否为低)
  109. uint8_t rx[3];
  110. if (HAL_GPIO_ReadPin(ADS1256_DRDY_GPIO_PORT, ADS1256_DRDY_PIN) != GPIO_PIN_RESET) {
  111. ADS_PRINTF("[ADS1256] DRDY pin not low, skipping read.\r\n");
  112. return false;
  113. }
  114. ADS1256_CS_LOW();
  115. HAL_SPI_Receive(&ADS1256_SPI_HANDLE, rx, 3, SPI_TIMEOUT);
  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. float ADS1256_ConvertToVoltage(int32_t raw, float vref, int gain) {
  122. return ((float)raw / 8388608.0f) * (vref / gain); // V = (raw / 2的23次方 —— 8388608)* (vref / gain) 单位V ,2的22次方= 4194304
  123. }
  124. void ADS1256_SetClockSource(uint8_t useInternal) // CLK = 0:使用外部晶振 1:使用内部晶振
  125. {
  126. if (useInternal > 1) return;
  127. uint8_t status = ADS1256_ReadRegister(ADS1256_REG_STATUS);
  128. if (useInternal)
  129. status |= (1 << 2); // CLK = 1:使用内部晶振
  130. else
  131. status &= ~(1 << 2); // CLK = 0:使用外部晶振
  132. ADS1256_WriteRegister(ADS1256_REG_STATUS, status);
  133. }
  134. bool ADS1256_IsUsingExternalClock(void)
  135. {
  136. uint8_t status = ADS1256_ReadRegister(ADS1256_REG_STATUS);
  137. return (status & (1 << 3)) != 0; // CLKSTAT
  138. }
  139. void ADS1256_Init(void) { // 初始化 ADS1256
  140. // ADS1256_Reset();
  141. // osDelay(50);
  142. // 默认外部晶振,连续采样模式
  143. HAL_GPIO_WritePin(GPIOB, ADS_SYNC_PDWN_Pin, GPIO_PIN_SET);
  144. HAL_GPIO_WritePin(GPIOB, ADS_SYNC_PDWN_Pin, GPIO_PIN_RESET);
  145. HAL_GPIO_WritePin(GPIOB, ADS_SYNC_PDWN_Pin, GPIO_PIN_SET);
  146. ADS1256_SetClockSource(0); // 0使用外部晶振 1内部晶振
  147. ADS1256_WriteRegister(ADS1256_REG_STATUS, 0x06); // 0000 0 110 自动校准开启(ACAL = 1), 输入缓冲器关闭(BUFEN = 0)
  148. ADS1256_WriteRegister(ADS1256_REG_ADCON, 0x20); // 时钟输出禁用(CLKOUT = 00), 增益为1倍(输入是几mV,增益增大至8)
  149. ADS1256_SetDataRate(ADS1256_DR_1000SPS); // ADS1256_DR_1000SPS
  150. ADS1256_SetChannel(ADS1256_MUX_AIN0_AINCOM); // AIN1 - AINCOM
  151. ADS1256_SendCommand(ADS1256_CMD_SELFCAL);// 启动自动增益和偏移校准 必须最后执行该指令
  152. ADS1256_SendCommand(ADS1256_CMD_RDATAC); // 连续采样
  153. }