/* 2020-12-10 Michael Nowak http://www.mino-elektronik.de Alle Angaben ohne Gewaehr ! */ #define TDC7200 #include "system_H750.h" // Befehl und Startadresse ausgeben void TDC_write(uint8_t cmd) { while(!(SPI1->SR & SPI_SR_TXP)); // freies FIFO abwarten *(__IO uint8_t *)&SPI1->TXDR = (uint8_t)(cmd); while(!(SPI1->SR & SPI_SR_TXC)); // Ausgabe abwarten } // RX-FIFO leeren void flush_SPI1(void) { while((SPI1->SR & (SPI_SR_RXWNE | SPI_SR_RXPLVL))) SPI1->RXDR; } // WERT holen uint8_t TDC_read(void) { uint8_t data; *(__IO uint8_t *)&SPI1->TXDR = 0; while(!(SPI1->SR & (SPI_SR_RXWNE | SPI_SR_RXPLVL))); data = *(__IO uint8_t *)&SPI1->RXDR; return(data); } void TDC_write_cmd(uint8_t adr, uint8_t val) { set_pin(GPIOB, TDC_SSN, 0); // Select auf '0' aktiv TDC_write(adr); // Adresse ausgeben TDC_write(val); // Wert ausgeben set_pin(GPIOB, TDC_SSN, 1); // Select auf '1' passiv flush_SPI1(); } void TDC_trigger(void) { set_pin(GPIOB, TDC_SSN, 0); // Select auf '0' aktiv *(__IO uint8_t *)&SPI1->TXDR = (uint8_t)(TDC_CONFIG1_WR); *(__IO uint8_t *)&SPI1->TXDR = (uint8_t)(CMD_FORCE_CAL+CMD_START_MEAS); while(!(SPI1->SR & SPI_SR_TXC)); // Ausgabe abwarten set_pin(GPIOB, TDC_SSN, 1); // Select auf '1' passiv flush_SPI1(); } uint32_t init_TDC7200(void) { volatile int n; int TDC_vorhanden = 1; // default TDC vorhanden RCC->AHB4ENR |= RCC_AHB4ENR_GPIOBEN | (RCC_AHB4ENR_GPIOCEN) | (RCC_AHB4ENR_GPIOEEN); // PortB+C+E aktivieren RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // SPI1 aktivieren GPIOE->MODER &= ~(CLR_MODER << (OSC_PWR * 2)); GPIOE->MODER |= (OUT << (OSC_PWR * 2)); // ENAB vom TDC7200 auf Ausgang GPIOC->MODER &= ~(CLR_MODER << (TDC_INTN * 2)); // auf Eingang GPIOC->PUPDR |= 1 << TDC_INTN * 2; // Pullup INTN einschalten GPIOB->MODER &= ~(CLR_MODER << (TDC_DIN * 2) | CLR_MODER << (TDC_DOUT * 2) | CLR_MODER << (TDC_SCLK * 2) | CLR_MODER << (TDC_SSN * 2)); // auf Eingang GPIOB->MODER |= (AF << (TDC_DIN * 2) | AF << (TDC_DOUT * 2) | AF << (TDC_SCLK * 2) | OUT << (TDC_SSN * 2)); // normaler Ausgang // Geschwindigkeit GPIOB->OSPEEDR |= (V_HIGH_SPEED << (TDC_DIN * 2) | V_HIGH_SPEED << (TDC_DOUT * 2) | V_HIGH_SPEED << (TDC_SCLK * 2) | V_HIGH_SPEED << (TDC_SSN * 2)); GPIOB->AFR[0] |= (AFR_SPI1 << (TDC_DIN * 4) | // AF für SPI1 auf PortB AFR_SPI1 << (TDC_DOUT * 4) | AFR_SPI1 << (TDC_SCLK * 4)); // SPI1->CFG1 = SPI_CFG1_MBR_1 | SPI_CFG1_MBR_0 | 7; // Taktteiler / 16 mit 8 bit: 12,5 MHz CLK SPI1->CFG1 = SPI_CFG1_MBR_1 | 7; // Taktteiler / 8 mit 8 bit: 25 MHz CLK // CPOL und CPHA auf 0: Datenausgabe bei positiver Flanke von Clock // MSB first SPI1->CFG2 = SPI_CFG2_AFCNTR | // PortB bits reserviert für SPI1 SPI_CFG2_SSOE | // SS-Pin aktivieren SPI_CFG2_SSM | // SS-Pin aktiv per Software SPI_CFG2_MASTER; // SPI1->CR1 |= SPI_CR1_SPE; // SPI1 einschalten SPI1->CR1 |= SPI_CR1_CSTART; // SPI1 einschalten set_pin(GPIOB, TDC_SSN, 1); // Select auf '1' F_ref10 = hse_value; // default für ext. Takt // power-on reset set_pin(GPIOE, ENAB, 0); // Select auf '0' passiv set_pin(GPIOB, TDC_SSN, 1); // Select auf '1' passiv for(n=0; n<1000; n++); set_pin(GPIOE, ENAB, 1); // Select auf '1' aktiv // Test, ob TDC richtig antwortet set_pin(GPIOB, TDC_SSN, 0); // Select auf '0' aktiv TDC_write(TDC_INT_MASK_RD); // INT_MASK lesen TDC_write(0); // Takt zum Auslesen des Bytes erzeugen TDC_read(); // ungültiges Byte ignorieren TDC_vorhanden = TDC_read(); set_pin(GPIOB, TDC_SSN, 1); // Select auf '1' passiv // TDC7200 starten if(TDC_vorhanden == TDC_INT_MASK_DEF) { // Resetwert erkannt TDC_write_cmd(TDC_INT_MASK_WR,CMD_NEW_MEAS_INT); // INT-auslösen TDC_write_cmd(TDC_CONFIG2_WR, 0x00); // 2-fach Abgleich (default) TDC_trigger(); return(TDC_vorhanden); } return(0); // kein TDC7200 erkannt } // 24 bit Ergebnisse holen uint32_t lese_TDC_CAL1(void) { uint32_t temp, n; set_pin(GPIOB, TDC_SSN, 0); // Select auf '0' aktiv SPI1->TXDR = (TDC_CAL1_RD); while(!(SPI1->SR & SPI_SR_TXC)); // vollständige Ausgabe abwarten set_pin(GPIOB, TDC_SSN, 1); // SSN wieder auf '1' for(n=0; n<4; n++) { temp <<= 8; temp |= *(__IO uint8_t *)&SPI1->RXDR; } return(temp & 0xffffff); } uint32_t lese_TDC_CAL2(void) { uint32_t temp, n; set_pin(GPIOB, TDC_SSN, 0); // Select auf '0' aktiv SPI1->TXDR = (TDC_CAL2_RD); while(!(SPI1->SR & SPI_SR_TXC)); // vollständige Ausgabe abwarten set_pin(GPIOB, TDC_SSN, 1); // SSN wieder auf '1' for(n=0; n<4; n++) { temp <<= 8; temp |= *(__IO uint8_t *)&SPI1->RXDR; } return(temp & 0xffffff); } uint32_t lese_TDC_TIME1(void) { uint32_t temp, n; set_pin(GPIOB, TDC_SSN, 0); // Select auf '0' aktiv SPI1->TXDR = (TDC_TIME1_RD); while(!(SPI1->SR & SPI_SR_TXC)); // vollständige Ausgabe abwarten set_pin(GPIOB, TDC_SSN, 1); // SSN wieder auf '1' for(n=0; n<4; n++) { temp <<= 8; temp |= *(__IO uint8_t *)&SPI1->RXDR; } return(temp & 0xffffff); }