該演示程序使用的芯片為:STM32F103C8T6
功能:
單片機采集ADS1292模塊數據,通過串口輸出。
串口:
UART1
波特率:115200
停止位:1
數據為:8
奇偶校驗:無
引腳定義及連線:
1292模塊--STM32F1:
VDD---3.3V/5V
GND---GND
DRDY---PA8
CS---PB12
SCK---PB13
MISO---PB14
MOSI---PB15
單片機源程序如下:
- #include "ADS1292.h"
- #include "spi.h"
- #include "delay.h"
- #include "usart.h"
- #include "Timer.h"
- #include "key.h"
- #include "led.h"
- #define DEBUG_ADS1292 //寄存器printf調試
- u8 ADS1292_REG[12]; //ads1292寄存器數組
- ADS1292_CONFIG1 Ads1292_Config1 ={DATA_RATE}; //CONFIG1
- ADS1292_CONFIG2 Ads1292_Config2 ={PDB_LOFF_COMP,PDB_REFBUF,VREF,CLK_EN,INT_TEST}; //CONFIG2
- ADS1292_CHSET Ads1292_Ch1set ={CNNNLE1_POWER,CNNNLE1_GAIN,CNNNLE1_MUX}; //CH1SET
- ADS1292_CHSET Ads1292_Ch2set ={CNNNLE2_POWER,CNNNLE2_GAIN,CNNNLE2_MUX}; //CH2SET
- ADS1292_RLD_SENS Ads1292_Rld_Sens ={PDB_RLD,RLD_LOFF_SENSE,RLD2N,RLD2P,RLD1N,RLD1P}; //RLD_SENS
- ADS1292_LOFF_SENS Ads1292_Loff_Sens ={FLIP2,FLIP1,LOFF2N,LOFF2P,LOFF1N,LOFF1P}; //LOFF_SENS
- ADS1292_RESP1 Ads1292_Resp1 ={RESP_DEMOD_EN1,RESP_MOD_EN,RESP_PH,RESP_CTRL}; //RSP1
- ADS1292_RESP2 Ads1292_Resp2 ={CALIB,FREQ,RLDREF_INT}; //RSP2
-
- //ADS1292的IO口初始化
- void ADS1292_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- EXTI_InitTypeDef EXTI_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);
- SPI2_Init();//初始化SPI引腳
- //250ns 頻率4.5M 發送八組時鐘需要23 us
- //125ns 頻率9M, 發送八組時鐘需要14 us
- //55ns 頻率18M 發送八組時鐘需要9.2us
- //30ns 36M 發送八組時鐘需要9.2us
- //手冊10頁里寫的最小時鐘周期為50ns
- //DRDY //待機時高電平,采集時低電平有效
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉輸入
- GPIO_Init(GPIOC, &GPIO_InitStructure);
- //CS
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- // //RESRT
- // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
- // GPIO_Init(GPIOA, &GPIO_InitStructure);
- // //START
- // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
- // GPIO_Init(GPIOA, &GPIO_InitStructure);
- // //CLKSEL
- // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
- // GPIO_Init(GPIOA, &GPIO_InitStructure);
- //DRDY中斷初始化
- EXTI_ClearITPendingBit(EXTI_Line8);//清除中斷標志
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource8);//選擇管腳
- EXTI_InitStructure.EXTI_Line=EXTI_Line8; //選擇中斷線路
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //設置為中斷請求,非事件請求
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿觸發
- EXTI_InitStructure.EXTI_LineCmd = ENABLE; //外部中斷使能
- EXTI_Init(&EXTI_InitStructure);
-
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //選擇中斷通道
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //搶占優先級
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子優先級
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中斷通道
- NVIC_Init(&NVIC_InitStructure);
-
- EXTI->IMR &= ~(EXTI_Line8);//屏蔽外部中斷
- ADS_CS=1;
- ADS1292_PowerOnInit();//上電復位,進入待機模式
- }
- volatile u8 ads1292_recive_flag=0; //數據讀取完成標志
- volatile u8 ads1292_Cache[9]; //數據緩沖區
- void EXTI9_5_IRQHandler(void)
- {
-
- if(EXTI->IMR&EXTI_Line8 && ADS_DRDY==0)//數據接收中斷
- {
- EXTI_ClearITPendingBit(EXTI_Line8);
- ADS1292_Read_Data(ads1292_Cache);//數據存到9字節緩沖區
- ads1292_recive_flag=1;
- }
- }
- //讀取72位的數據1100+LOFF_STAT[4:0]+GPIO[1:0]+13個0+2CHx24位,共9字節
- // 1100 LOFF_STAT[4 3 2 1 0 ] //導聯脫落相關的信息在LOFF_STAT寄存器里
- // RLD 1N2N 1N2P 1N1N 1N1P
- // 例 C0 00 00 FF E1 1A FF E1 52
- u8 ADS1292_Read_Data(u8 *data)//72M時鐘下函數耗時大約10us 8M時鐘下 函數耗時大約 100us
- {
- u8 i;
-
- ADS_CS=0;//讀9個字節的數據
- //delay_us(10);
- for(i=0;i<9;i++)
- {
- *data=ADS1292_SPI(0X00);
- data++;
- }
- //delay_us(10);
- ADS_CS=1;
- return 0;
- }
- //設置寄存器數組
- void ADS1292_SET_REGBUFF(void)
- {
- ADS1292_REG[ID] = ADS1292_DEVICE;//ID只讀
-
- ADS1292_REG[CONFIG1] = 0x00; //0000 0aaa [7] 0連續轉換模式 [6:3] 必須為0
- ADS1292_REG[CONFIG1] |= Ads1292_Config1.Data_Rate;//[2:0] aaa 采樣率設置采樣率
- ADS1292_REG[CONFIG2] = 0x00; //1abc d0e1 [7] 必須為1 [2] 必須為0 [0] 設置測試信號為1HZ、±1mV方波
- ADS1292_REG[CONFIG2] |= Ads1292_Config2.Pdb_Loff_Comp<<6; //[6]a 導聯脫落比較器是否掉電
- ADS1292_REG[CONFIG2] |= Ads1292_Config2.Pdb_Refbuf<<5; //[5]b 內部參考緩沖器是否掉電
- ADS1292_REG[CONFIG2] |= Ads1292_Config2.Vref<<4; //[4]c 內部參考電壓設置,默認2.42V
- ADS1292_REG[CONFIG2] |= Ads1292_Config2.Clk_EN<<3; //[3]d CLK引腳輸出時鐘脈沖?
- ADS1292_REG[CONFIG2] |= Ads1292_Config2.Int_Test<<1; //[1]e 是否打開內部測試信號,
- ADS1292_REG[CONFIG2] |= 0x81;//設置默認位
-
- ADS1292_REG[LOFF] = 0x10;//[7:5] 設置導聯脫落比較器閾值 [4] 必須為1 [3:2] 導聯脫落電流幅值 [1] 必須為0 [0] 導聯脫落檢測方式 0 DC 1 AC
- ADS1292_REG[CH1SET] = 0x00; //abbb cccc
- ADS1292_REG[CH1SET] |=Ads1292_Ch1set.PD<<7; //[7] a 通道1斷電?
- ADS1292_REG[CH1SET] |=Ads1292_Ch1set.GAIN<<4; //[6:4]bbb 設置PGA增益
- ADS1292_REG[CH1SET] |=Ads1292_Ch1set.MUX; //[3:0]cccc 設置通道1輸入方式
- ADS1292_REG[CH2SET] = 0x00; //abbb cccc
- ADS1292_REG[CH2SET] |=Ads1292_Ch2set.PD<<7; //[7] a 通道2斷電?
- ADS1292_REG[CH2SET] |=Ads1292_Ch2set.GAIN<<4; //[6:4]bbb 設置PGA增益
- ADS1292_REG[CH2SET] |=Ads1292_Ch2set.MUX; //[3:0]cccc 設置通道2輸入方式
-
- ADS1292_REG[RLD_SENS] = 0X00; //11ab cdef [7:6] 11 PGA斬波頻率 fMOD/4
- ADS1292_REG[RLD_SENS] |=Ads1292_Rld_Sens.Pdb_Rld<<5; //[5]a 該位決定RLD緩沖電源狀態
- ADS1292_REG[RLD_SENS] |=Ads1292_Rld_Sens.Rld_Loff_Sense<<4; //[4]b 該位使能RLD導聯脫落檢測功能
- ADS1292_REG[RLD_SENS] |=Ads1292_Rld_Sens.Rld2N<<3; //[3]c 這個位控制通道2負輸入 用于右腿驅動的輸出
- ADS1292_REG[RLD_SENS] |=Ads1292_Rld_Sens.Rld2P<<2; //[2]d 該位控制通道2正輸入 用于右腿驅動的輸出
- ADS1292_REG[RLD_SENS] |=Ads1292_Rld_Sens.Rld1N<<1; //[1]e 這個位控制通道1負輸入 用于右腿驅動的輸出
- ADS1292_REG[RLD_SENS] |=Ads1292_Rld_Sens.Rld1P; //[0]f 該位控制通道1正輸入 用于右腿驅動的輸出
- ADS1292_REG[RLD_SENS] |= 0xc0;//設置默認位
- ADS1292_REG[LOFF_SENS] = 0X00; //00ab cdef [7:6] 必須為0
- ADS1292_REG[LOFF_SENS] |=Ads1292_Loff_Sens.Flip2<<5; //[5]a 這個位用于控制導聯脫落檢測通道2的電流的方向
- ADS1292_REG[LOFF_SENS] |=Ads1292_Loff_Sens.Flip1<<4; //[4]b 這個位控制用于導聯脫落檢測通道1的電流的方向
- ADS1292_REG[LOFF_SENS] |=Ads1292_Loff_Sens.Loff2N<<3; //[3]c 該位控制通道2負輸入端的導聯脫落檢測
- ADS1292_REG[LOFF_SENS] |=Ads1292_Loff_Sens.Loff2P<<2; //[2]d 該位控制通道2正輸入端的導聯脫落檢測
- ADS1292_REG[LOFF_SENS] |=Ads1292_Loff_Sens.Loff1N<<1; //[1]e 該位控制通道1負輸入端的導聯脫落檢測
- ADS1292_REG[LOFF_SENS] |=Ads1292_Loff_Sens.Loff1P; //[0]f 該位控制通道1正輸入端的導聯脫落檢測
-
- ADS1292_REG[LOFF_STAT] = 0x00; //[6]0 設置fCLK和fMOD之間的模分頻比 fCLK=fMOD/4 [4:0]只讀,導聯脫落和電極連接狀態
-
- ADS1292_REG[RESP1] = 0X00;//abcc cc1d
- ADS1292_REG[RESP1] |=Ads1292_Resp1.RESP_DemodEN<<7;//[7]a 這個位啟用和禁用通道1上的解調電路
- ADS1292_REG[RESP1] |=Ads1292_Resp1.RESP_modEN<<6; //[6]b 這個位啟用和禁用通道1上的調制電路
- ADS1292_REG[RESP1] |=Ads1292_Resp1.RESP_ph<<2; //[5:2]c 這些位控制呼吸解調控制信號的相位
- ADS1292_REG[RESP1] |=Ads1292_Resp1.RESP_Ctrl; //[0]d 這個位設置呼吸回路的模式
- ADS1292_REG[RESP1] |= 0x02;//設置默認位
-
- ADS1292_REG[RESP2] = 0x00; //a000 0bc1 [6:3]必須為0 [0]必須為1
- ADS1292_REG[RESP2] |= Ads1292_Resp2.Calib<<7; //[7]a 啟動通道偏移校正?
- ADS1292_REG[RESP2] |= Ads1292_Resp2.freq<<2; //[2]b 呼吸頻率設置
- ADS1292_REG[RESP2] |= Ads1292_Resp2.Rldref_Int<<1; //[1]c RLDREF信號源外部饋電?
- ADS1292_REG[RESP2] |= 0X01;//設置默認位
-
- ADS1292_REG[GPIO] = 0x0C; //GPIO設為輸入 [7:4]必須為0 [3:2]11 GPIO為輸入 [1:0] 設置輸入時,指示引腳電平,設置輸出時控制引腳電平
- }
- //通過SPI總線與ADS1292通信
- u8 ADS1292_SPI(u8 com)
- {
- return SPI2_ReadWriteByte(com);
- }
- //寫命令
- void ADS1292_Send_CMD(u8 data)
- {
- ADS_CS=0;
- delay_us(100);
- ADS1292_SPI(data);
- delay_us(100);
- ADS_CS=1;
- }
- /*ADS1291、ADS1292和ADS1292R串行接口以字節形式解碼命令,需要4個tCLK周期來解碼和執行.
- 因此,在發送多字節命令時,4 tCLK周期必須將一個字節(或操作碼)的結束與下一個字節(或操作碼)分開。
- 假設CLK(時鐘)為512 kHz,則tSDECODE (4 tCLK)為7.8125 us。
- 當SCLK(數據速率)為16mhz時,一個字節可以在500ns中傳輸,此字節傳輸時間不符合tSDECODE規范;
- 因此,必須插入一個延遲,以便第二個字節的末尾晚于7.3125us到達。
- 如果SCLK為1 MHz,則在8u秒內傳輸一個字節。由于此傳輸時間超過tSDECODE規范,處理器可以不延遲地發送后續字節。
- 在后面的場景中,可以對串行端口進行編程,使其從每個循環的單字節傳輸轉移到多個字節*/
- //讀寫多個寄存器
- void ADS1292_WR_REGS(u8 reg,u8 len,u8 *data)
- {
- u8 i;
- ADS_CS=0;
- delay_us(100);
- ADS1292_SPI(reg);
- delay_us(100);
- ADS1292_SPI(len-1);
- if(reg&0x40) //寫
- {
- for(i=0;i<len;i++)
- {
- delay_us(100);
- ADS1292_SPI(*data);
- data++;
- }
- }
- else //讀
- {
- for(i=0;i<len;i++)
- {
- delay_us(100);
- *data = ADS1292_SPI(0);
- data++;
- }
- }
- delay_us(100);
- ADS_CS=1;
- }
- //寄存器數組寫入寄存器
- u8 ADS1292_WRITE_REGBUFF(void)
- {
- u8 i,res=0;
- u8 REG_Cache[12]; //存儲寄存器數據
- ADS1292_SET_REGBUFF();//設置寄存器數組
- ADS1292_WR_REGS(WREG|CONFIG1,11,ADS1292_REG+1);//數組變量寫入寄存器
- delay_ms(10);
- ADS1292_WR_REGS(RREG|ID,12,REG_Cache);//讀寄存器
- delay_ms(10);
-
- // #ifdef DEBUG_ADS1292
- // printf("WRITE REG:\r\n");
- // for(i=0;i<12;i++ )//要寫的數據
- // printf("%d %x\r\n",i,ADS1292_REG[i]);
- // printf("READ REG:\r\n");
- // #endif
-
-
- for(i=0;i<12;i++ ) //檢查寄存器
- {
- if(ADS1292_REG[i] != REG_Cache[i])
- {
- if(i!= 0 && i!=8 && i != 11) //0 8 和11是ID 導聯脫落和GPIO相關
- res=1;
- else
- continue;
- }
- // #ifdef DEBUG_ADS1292
- // printf("%d %x\r\n",i,REG_Cache[i]); //讀到的數據
- // #endif
- }
- #ifdef DEBUG_ADS1292
- if(res == 0)
- printf("REG write success\r\n");
- else
- printf("REG write err\r\n");
- #endif
- return res;
- }
- void ADS1292_PowerOnInit(void)
- {
- u8 i;
- u8 REG_Cache[12];
-
- // ADS_CLKSEL=1;//啟用內部時鐘
- // ADS_START=0; //停止數據輸出
- // ADS_RESET=0; //復位
- // delay_ms(1000);
- // ADS_RESET=1;//芯片上電,可以使用
- // delay_ms(100); //等待穩定
-
- ADS1292_Send_CMD(SDATAC);//發送停止連續讀取數據命令
- delay_ms(100);
- ADS1292_Send_CMD(RESET);//復位
- delay_s(1);
- ADS1292_Send_CMD(SDATAC);//發送停止連續讀取數據命令
- delay_ms(100);
-
- //#ifdef DEBUG_ADS1292
- // ADS1292_WR_REGS(RREG|ID,12,REG_Cache);
- // printf("read default REG:\r\n");
- // for(i=0;i<12;i++ ) //讀默認寄存器
- // printf("%d %x\r\n",i,REG_Cache[i]);
- //#endif
- //ADS1292_Send_CMD(STANDBY);//進入待機模式
- }
- //設置通道1內部1mV測試信號
- u8 ADS1292_Single_Test(void) //注意1292R開了呼吸解調,會對通道一的內部測試信號波形造成影響,這里只參考通道2即可,1292不受影響
- {
- u8 res=0;
- Ads1292_Config2.Int_Test = INT_TEST_ON;//打開內部測試信號
- Ads1292_Ch1set.MUX=MUX_Test_signal;//測試信號輸入
- Ads1292_Ch2set.MUX=MUX_Test_signal;//測試信號輸入
-
- if(ADS1292_WRITE_REGBUFF())//寫入寄存器
- res=1;
- delay_ms(10);
- return res;
- }
- //設置內部噪聲測試
- u8 ADS1292_Noise_Test(void)
- {
- u8 res=0;
- Ads1292_Config2.Int_Test = INT_TEST_OFF;//關內部測試信號
- Ads1292_Ch1set.MUX = MUX_input_shorted;//輸入短路
- Ads1292_Ch2set.MUX = MUX_input_shorted;//輸入短路
- if(ADS1292_WRITE_REGBUFF())//寫入寄存器
- res=1;
- delay_ms(10);
- return res;
- }
- //正常信號采集模式
- u8 ADS1292_Single_Read(void)
- {
- u8 res=0;
- Ads1292_Config2.Int_Test = INT_TEST_OFF;//關內部測試信號
- Ads1292_Ch1set.MUX = MUX_Normal_input;//普通電極輸入
- Ads1292_Ch2set.MUX = MUX_Normal_input;//普通電極輸入
-
- if(ADS1292_WRITE_REGBUFF())//寫入寄存器
- res=1;
- delay_ms(10);
- return res;
- }
- //配置ads1292采集方式
- u8 Set_ADS1292_Collect(u8 mode)
- {
- u8 res;
-
- delay_ms(10);
- switch(mode)//設置采集方式
- {
- case 0:
- res =ADS1292_Single_Read();
- break;
- case 1:
- res =ADS1292_Single_Test();
- break;
- case 2:
- res =ADS1292_Noise_Test();
- break;
- }
- if(res)return 1;//寄存器設置失敗
- ADS1292_Send_CMD(RDATAC); //啟動連續模式
- delay_ms(10);
- ADS1292_Send_CMD(START); //發送開始數據轉換(等效于拉高START引腳)
- delay_ms(10);
- return 0;
- }
復制代碼
- #include "sys.h" //系統配置
- #include "delay.h" //延時
- #include "usart.h" //串口
- #include "led.h"
- #include "ADS1292.h"
- #include "Timer.h"
- #include "dma.h"
- u8 xinlv;
- extern u8 xinlv1;
- s32 get_volt(u32 num);
- u8 flag;
- u16 flag1;
- //main
- int main(void)
- {
- u8 res,i,sum;
- u8 data_to_send[60];//串口發送緩存
- u8 usbstatus=0;
- u32 cannle[2]; //存儲兩個通道的數據
- s32 p_Temp[2]; //數據緩存
-
- data_to_send[0]=0xAA;
- data_to_send[1]=0xAA;
- data_to_send[2]=0xF1;
- data_to_send[3]=8;
- data_to_send[13] = 0X0D; //校驗和
- data_to_send[14] = 0X0A; //校驗和
- //初始化系統時鐘 72M
- SystemInit();
- delay_init();
- delay_ms(100);
- uart1_init(500000);//串口初始化為115200
- DMA_Config(DMA1_Channel4,(u32)&USART1->DR,(u32)data_to_send);//串口1DMA設置
- USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //DMA
- LED_Init();
- ADS1292_Init(); //初始化ads1292
- while(Set_ADS1292_Collect(0))
- {
- printf("1292寄存器設置失敗\r\n");
- delay_s(1);
- }
- printf("寄存器設置成功\r\n");
- delay_s(1);
- TIM2_Init(50,1439);//系統指示
- TIM4_Init(50,1439);//打印心率
-
- EXTI->IMR |= EXTI_Line8;//開DRDY中斷
- while(1)//循環發送數據
- {
-
- if(ads1292_recive_flag==1)
- {
- flag1++;
- cannle[0]=ads1292_Cache[3]<<16 | ads1292_Cache[4]<<8 | ads1292_Cache[5];//獲取原始數據
-
- cannle[1]=ads1292_Cache[6]<<16 | ads1292_Cache[7]<<8 | ads1292_Cache[8]; //
-
- p_Temp[0] = get_volt(cannle[0]); //把采到的3個字節轉成有符號32位數
-
- p_Temp[1] = get_volt(cannle[1]); //把采到的3個字節轉成有符號32位數
-
-
- cannle[0] = p_Temp[0];
-
- cannle[1] = p_Temp[1];
- data_to_send[4]=cannle[0]>>24; //25-32位
- data_to_send[5]=cannle[0]>>16; //17-24
- data_to_send[6]=cannle[0]>>8; //9-16
- data_to_send[7]=cannle[0]; //1-8
- data_to_send[8]=cannle[1]>>24; //25-32位
- data_to_send[9]=cannle[1]>>16; //17-24
- data_to_send[10]=cannle[1]>>8; //9-16
- data_to_send[11]=cannle[1]; //1-8
-
- for(i=0;i<12;i++)
- sum += data_to_send[i];
- // printf("%d\r\n",sum);
- data_to_send[12] = sum; //校驗和
- // DMA_Enable(DMA1_Channel4,13);//串口1DMA
-
- ads1292_recive_flag=0;
- sum = 0;
-
- if((p_Temp[1]>265000)&&(flag==1))
- {
- xinlv++;
- flag=0;
- }
- else if((p_Temp[1]<265000)&&(flag==0))
- flag=1;
- }
-
- }
- }
- /*功能:把采到的3個字節轉成有符號32位數 */
- s32 get_volt(u32 num)
- {
- s32 temp;
- temp = num;
- temp <<= 8;
- temp >>= 8;
- return temp;
- }
復制代碼
Keil代碼下載:
代碼.7z
(207.13 KB, 下載次數: 50)
2023-3-21 20:01 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|