0
好久没有发新的帖子了,最近一直都在调试IIC的驱动部分,终于让我调试通过了,下面就来记录一下!!!这次调试花了比较久的时间,中间也遇到了各种坑,最后发现其实大部分都是因为自己对器件的不熟悉导致的。。。话不多说,先上代码!!!
- /*
- * main.c
- *
- * Created on: 2016年11月22日
- * Author: SEELE
- */
- #include
- #include
- #include "xil_printf.h"
- #include "xparameters.h"
- #include "xiic.h"
- #include "xintc.h"
- #include "xil_exception.h"
- #include "xenv.h"
- #define BMP180_ADDRESS 0x77 /*actual address is 0xEE*/
- #define LED_DELAY 500000
- const unsigned char OSS = 0; // Oversampling Setting
- #define IIC_DEVICE_ID XPAR_IIC_0_DEVICE_ID
- #define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
- #define INTC_IIC_INTERRUPT_ID XPAR_INTC_0_IIC_0_VEC_ID
- XIic Iic;
- XIntc InterruptController;
- u8 BMPIicAddr;
- static int SetupInterruptSystem(XIic *IicPtr);
- static void RecvHandler(XIic *InstancePtr);
- static void SendHandler(XIic *InstancePtr);
- static void StatusHandler(void *CallbackRef, int Status);
- volatile int Delay;
- s16 ac1;
- s16 ac2;
- s16 ac3;
- u16 ac4;
- u16 ac5;
- u16 ac6;
- s16 b1;
- s16 b2;
- s16 mb;
- s16 mc;
- s16 md;
- u8 WriteBuffer[10];
- u8 Readbuffer[10];
- volatile u8 TransmitComplete;
- volatile u8 ReceiveComplete;
- // b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)
- // so ...Temperature(...) must be called before ...Pressure(...).
- long b5;
- int IicBMP180_Int()
- {
- int Status;
- XIic_Config *ConfigPtr;
- BMPIicAddr = BMP180_ADDRESS;
- ConfigPtr = XIic_LookupConfig(IIC_DEVICE_ID);
- if (ConfigPtr == NULL) {
- return XST_FAILURE;
- }
- Status = XIic_CfgInitialize(&Iic, ConfigPtr,
- ConfigPtr->BaseAddress);
- if (Status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- XIic_SetRecvHandler(&Iic,&Iic,
- (XIic_Handler) RecvHandler);
- XIic_SetStatusHandler(&Iic,&Iic,
- (XIic_StatusHandler) StatusHandler);
- XIic_SetSendHandler(&Iic,&Iic,
- (XIic_Handler) SendHandler);
- Status = SetupInterruptSystem(&Iic);
- if (Status != XST_SUCCESS){
- return XST_FAILURE;
- }
- Status = XIic_SetAddress(&Iic, XII_ADDR_TO_SEND_TYPE, BMPIicAddr);
- if (Status != XST_SUCCESS)
- {
- return XST_FAILURE;
- }
- return XST_SUCCESS;
- }
- static int SetupInterruptSystem(XIic *IicPtr)
- {
- int Status;
- Status = XIntc_Initialize(&InterruptController,INTC_DEVICE_ID);
- if (Status != XST_SUCCESS){
- return XST_FAILURE;
- }
- Status = XIntc_Connect(&InterruptController, INTC_IIC_INTERRUPT_ID,
- (XInterruptHandler)XIic_InterruptHandler, IicPtr);
- if (Status != XST_SUCCESS){
- return XST_FAILURE;
- }
- Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
- if (Status != XST_SUCCESS){
- return XST_FAILURE;
- }
- XIntc_Enable(&InterruptController, INTC_IIC_INTERRUPT_ID);
- if (Status != XST_SUCCESS){
- return XST_FAILURE;
- }
- Xil_ExceptionInit();
- Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
- (Xil_ExceptionHandler)XIntc_InterruptHandler,
- &InterruptController);
- Xil_ExceptionEnable();
- return XST_SUCCESS;
- }
- int Bmp180WriteData(u16 ByteCount)
- {
- int Status;
- TransmitComplete = 1;
- Iic.Stats.TxErrors = 0;
- Status = XIic_Start(&Iic);
- if (Status != XST_SUCCESS)
- {
- return XST_FAILURE;
- }
- Status = XIic_MasterSend(&Iic,WriteBuffer, ByteCount);
- if (Status != XST_SUCCESS)
- {
- return XST_FAILURE;
- }
- while ((TransmitComplete) || (XIic_IsIicBusy(&Iic) == TRUE)) {
- if (Iic.Stats.TxErrors != 0) {
- Status = XIic_Start(&Iic);
- if (Status != XST_SUCCESS){
- return XST_FAILURE;
- }
- if (!XIic_IsIicBusy(&Iic)){
- Status = XIic_MasterSend(&Iic,
- WriteBuffer,
- ByteCount);
- if (Status == XST_SUCCESS){
- Iic.Stats.TxErrors = 0;
- }
- else {
- }
- }
- }
- }
- Status = XIic_Stop(&Iic);
- if (Status != XST_SUCCESS){
- return XST_FAILURE;
- }
- return XST_SUCCESS;
- }
- int Bmp180ReadData(u8 add,u8 *BufferPtr, u16 ByteCount)
- {
- int Status;
- ReceiveComplete = 1;
- WriteBuffer[0] = add;
- Status = Bmp180WriteData(0x01);
- if (Status != XST_SUCCESS)
- {
- return XST_FAILURE;
- }
- Status = XIic_Start(&Iic);
- if (Status != XST_SUCCESS){
- return XST_FAILURE;
- }
- Status = XIic_MasterRecv(&Iic, BufferPtr, ByteCount);
- if (Status != XST_SUCCESS)
- {
- return XST_FAILURE;
- }
- while ((ReceiveComplete) || (XIic_IsIicBusy(&Iic) == TRUE)) {
- }
- Status = XIic_Stop(&Iic);
- if (Status != XST_SUCCESS){
- return XST_FAILURE;
- }
- return XST_SUCCESS;
- }
- s16 bmp180ReadInt(u8 Address)
- {
- u8 data[2] = {0,0};
- Bmp180ReadData(Address,data,2);
- return (s16) data[0]<<8 | data[1];
- }
- void bmp180Calibration()
- {
- ac1 = bmp180ReadInt(0xAA);
- ac2 = bmp180ReadInt(0xAC);
- ac3 = bmp180ReadInt(0xAE);
- ac4 = bmp180ReadInt(0xB0);
- ac5 = bmp180ReadInt(0xB2);
- ac6 = bmp180ReadInt(0xB4);
- b1 = bmp180ReadInt(0xB6);
- b2 = bmp180ReadInt(0xB8);
- mb = bmp180ReadInt(0xBA);
- mc = bmp180ReadInt(0xBC);
- md = bmp180ReadInt(0xBE);
- }
- u16 bmp180ReadUT()
- {
- u16 ut;
- //write 0x2e into register 0xf4
- WriteBuffer[0] = 0xF4;
- WriteBuffer[1] = 0x2E;
- Bmp180WriteData(2);
- for (Delay = 0; Delay < LED_DELAY; Delay++);
- ut = bmp180ReadInt(0xF6);
- return ut;
- }
- float bmp180GetTemperature(u16 ut)
- {
- long x1, x2;
- x1 = (((long)ut - (long)ac6)*(long)ac5)>>15;
- x2 = ((long)mc << 11)/(x1 + md);
- b5 = x1 + x2;
- float temp = ((b5 + 8)>>4);
- temp = temp / 10;
- return temp;
- }
- u32 bmp180ReadUP()
- {
- u8 data[3];
- u32 up = 0;
- WriteBuffer[0] = 0xF4;
- WriteBuffer[1] = (0x34 + (OSS<<6));
- Bmp180WriteData(2);
- udelay((2 + (3<
- for (Delay = 0; Delay < LED_DELAY; Delay++);
- u8 add = 0xF6;
- Bmp180ReadData(add,data,3);
- up = (((unsigned long)data[0]<<16) | ((unsigned long)data[1]<<8) | (unsigned long)data[2]) >> (8-OSS);
- return up;
- }
- s32 bmp180GetPressure(u32 up)
- {
- long x1, x2, x3, b3, b6, p;
- unsigned long b4, b7;
- b6 = b5 - 4000;
- // Calculate B3
- x1 = (b2 * (b6 * b6)>>12)>>11;
- x2 = (ac2 * b6)>>11;
- x3 = x1 + x2;
- b3 = (((((long)ac1)*4 + x3)<>2;
- // Calculate B4
- x1 = (ac3 * b6)>>13;
- x2 = (b1 * ((b6 * b6)>>12))>>16;
- x3 = ((x1 + x2) + 2)>>2;
- b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
- b7 = ((unsigned long)(up - b3) * (50000>>OSS));
- if (b7 < 0x80000000)
- p = (b7<<1)/b4;
- else
- p = (b7/b4)<<1;
- x1 = (p>>8) * (p>>8);
- x1 = (x1 * 3038)>>16;
- x2 = (-7357 * p)>>16;
- p += (x1 + x2 + 3791)>>4;
- long temp = p;
- return temp;
- }
- float calcAltitude(float pressure)
- {
- float A = pressure/101325;
- float B = 1/5.25588;
- float C = pow(A,B);
- C = 1 - C;
- C = C / 0.0000225577;
- return C;
- }
- int main()
- {
- float temperature = 0.0;
- float pressure = 0.0;
- u32 up;
- u16 ut;
- float atm = 0.0;
- float altitude = 0.0;
- xil_printf("hello world!nr");
- IicBMP180_Int();
- bmp180Calibration();
- while (1)
- {
- ut = bmp180ReadUT();
- temperature = bmp180GetTemperature(ut);
- xil_printf("temp = %drn",(int)temperature);
- for (Delay = 0; Delay < LED_DELAY; Delay++);
- up = bmp180ReadUP();
- pressure = bmp180GetPressure(up);
- xil_printf("pressure = %drn",(int)pressure);
- for (Delay = 0; Delay < LED_DELAY; Delay++);
- }
- return 0;
- };
- /*****************************************************************************/
- /**
- * This receive handler is called asynchronously from an interrupt context and
- * and indicates that data in the specified buffer was received. The byte count
- * should equal the byte count of the buffer if all the buffer was filled.
- *
- * @param CallBackRef is a pointer to the IIC device driver instance which
- * the handler is being called for.
- * @param ByteCount indicates the number of bytes remaining to be received of
- * the requested byte count. A value of zero indicates all requested
- * bytes were received.
- *
- * @return None.
- *
- * @notes None.
- *
- ****************************************************************************/
- static void RecvHandler(XIic *InstancePtr)
- {
- ReceiveComplete = 0;
- }
- /*****************************************************************************/
- /**
- * This status handler is called asynchronously from an interrupt context and
- * indicates that the conditions of the IIC bus changed. This handler should
- * not be called for the application unless an error occurs.
- *
- * @param CallBackRef is a pointer to the IIC device driver instance which the
- * handler is being called for.
- * @param Status contains the status of the IIC bus which changed.
- *
- * @return None.
- *
- * @notes None.
- *
- ****************************************************************************/
- static void StatusHandler(void *CallbackRef, int Status)
- {
- }
- static void SendHandler(XIic *InstancePtr)
- {
- TransmitComplete = 0;
- }
复制代码
上面这部分是全部代码,下面是运行结果
其中气压值对应的Pa,温度对应的是摄氏度,我查了一下还是很准的。
这款BMP180温度气压模块是一款高精度,小封装的温度气压传感器,可以用来做一下海拔高度的计算。不过这里我仅仅是读取了温度值和气压值。在模块的内部存储了11个校准系数用来计算温度值和气压值。
而且在使用的过程中需要先计算出温度值,才能计算气压值。
上图就是存储在内部的校准参数。在BMP180的手册中详细描述了BMP180的计算流程,如下图所示。
在驱动的过程中也遇到了很多坑,主要是在延迟上面,由于器件要求每次使能采集温度和气压,需要延迟4.5ms。
而我一开始使用udelay()函数进行延时,发送怎么读取温度和气压都不对,而单独读取温度是对的。搞得我以为是IP核的配置有问题,最后发现是udelay()函数根本就没有定义,所以根本没有延时,最后试用了最简单的for(;;)实现了延时功能,结果终于正确了!!!!
附件中提供了,iic软核的datasheet,在开发之前看一下还是有很大帮助的!!!
|
|