参考:https://durant35.github.io/2017/11/30/TACouses_ES2017_MCU_GPIO/
TMP006温度计有三线:SCL,sda (Pa6 Pa7)和一根中断线连接到(PA2,这里没有使用中断功能)。
对于GPIO口,有两种功能:
A)作为I/O功能(也就是常说的GPIO功能)
B)也有很多的内置外设(片上外设),像 I2C,ISP,USART等,为了节省引出管脚,这些内置外设基本上是与 I/O 口共用管脚的,也就是alt funtion(也就是 I/O 管脚的复用功能)
注:对于开发板的IIC1的SCL,SDA是借用 Pa6 Pa7的alt funtion(也就是 I/O 管脚的复用功能),所以要先port A 的时钟使能,然后才能配置 Pa6 Pa7,比如的alt funtion,enable digital I/O。
1.先初始化IIC1:
void i2cinit(void){
SYSCTL_RCGCI2C_R |= 0x0002; // 1a) 激活 I2C1本身的时钟
SYSCTL_RCGCGPIO_R |= 0x0001; // 1b) 对TIVAC 必须先使能对应时钟,之后才能使能 Port A的 各种配置
while((SYSCTL_PRGPIO_R&0x01) == 0){};// allow time for clock to stabilize
// 2) no need to unlock PA7-6
GPIO_PORTA_AMSEL_R &= ~0xC0; // 3) 禁用 PA7-6的模拟功能
GPIO_PORTA_PCTL_R = (GPIO_PORTA_PCTL_R&0x00FFFFFF)+0x33000000;
GPIO_PORTA_ODR_R |= 0x80; // 5) enable open drain on PA7 only
GPIO_PORTA_AFSEL_R |= 0xC0; // 6) 使能 PA7-6的多路复用功能(就是配置 PA7-6 为 I2C1)
GPIO_PORTA_DEN_R |= 0xC0; // 7) 配置 PA7-6 e数字IO模式,而不是模拟IO
I2C1_MCR_R = I2C_MCR_MFE; // 8) master function enable
I2C1_MTPR_R = 39; // 9) configure for 100 kbps clock
// 20*(TPR+1)*12.5ns = 10us, with TPR=39
}
2. BSP_TempSensor_Init
// Initialize a GPIO pin for input, which corresponds
// pins J2.11 (Temperature Sensor interrupt). 这里我们没用到中断读温度,可以不配置PA2
// two I2C pins J1.9 (SCL) and J1.10 (SDA).
void BSP_TempSensor_Init(void){
i2cinit();
// 1) activate clock for Port A (done in i2cinit())
// allow time for clock to stabilize (done in i2cinit())
// 2) no need to unlock PA2
GPIO_PORTA_AMSEL_R &= ~0x04; // 3) disable analog on PA2
// GPIO_PORTA_AMSEL_R |= 0x04; // 4) configure PA2 as GPIO
GPIO_PORTA_PCTL_R = (GPIO_PORTA_PCTL_R&0xFFFFF0FF)+0x00000000;
GPIO_PORTA_DIR_R &= ~0x04; // 5) make PA2 input
GPIO_PORTA_AFSEL_R &= ~0x04; // 6) disable alt funct on PA2
GPIO_PORTA_DEN_R |= 0x04; // 7) enable digital I/O on PA2
}
3. BSP_TempSensor_Start
void static tempsensorstart(uint8_t slaveAddress){
I2C_Send3(slaveAddress, 0x02, 0x75, 0x00);
}
//解释值,转换成温度
void static tempsensorend(uint8_t slaveAddress, int32_t *sensorV, int32_t *localT){
int16_t raw;
I2C_Send1(slaveAddress, 0x00); // pointer register 0x00 = Sensor Voltage Register
raw = I2C_Recv2(slaveAddress);
*sensorV = raw*15625; // 156.25 nV per LSB
I2C_Send1(slaveAddress, 0x01); // pointer register 0x01 = Local Temperature Register
raw = I2C_Recv2(slaveAddress);
*localT = (raw>>2)*3125; // 0.03125 C per LSB
}
#define TEMPINT (*((volatile uint32_t *)0x40004010)) /* PA2 */
int TempBusy = 0; // 0 = idle; 1 = measuring
void BSP_TempSensor_Input(int32_t *sensorV, int32_t *localT){
int32_t volt, temp;
TempBusy = 1;
tempsensorstart(0x40);
while(TEMPINT == 0x04){}; // wait for conversion to complete
tempsensorend(0x40, &volt, &temp);
*sensorV = volt;
*localT = temp;
TempBusy = 0;
}
// ------------BSP_TempSensor_Start------------
// Assumes: BSP_TempSensor_Init() has been called
void BSP_TempSensor_Start(void){
if(TempBusy == 0){
// no measurement is in progress, so start one
TempBusy = 1;
tempsensorstart(0x40);
}
}
int BSP_TempSensor_End(int32_t *sensorV, int32_t *localT){
int32_t volt, temp;
if(TempBusy == 0){
// no measurement is in progress, so start one
TempBusy = 1;
tempsensorstart(0x40);
return 0; // measurement needs more time to complete
} else{
// measurement is in progress
if(TEMPINT == 0x04){
return 0; // measurement needs more time to complete
} else{
tempsensorend(0x40, &volt, &temp);
*sensorV = volt;
*localT = temp;
TempBusy = 0;
return 1; // measurement is complete; pointers valid
}
}
}
5 调用
void Task4(void){int32_t voltData,tempData;
int done;
BSP_TempSensor_Init();
while(1){
TExaS_Task4(); // records system time in array, toggles virtual logic analyzer
Profile_Toggle4(); // viewed by a real logic analyzer to know Task4 started
BSP_TempSensor_Start();
done = 0;
while(done == 0){
done = BSP_TempSensor_End(&voltData,&tempData); // waits about 1 sec
}
TemperatureData = tempData/10000;
}
}