Cyfrowy kompas na STM32 z czujnikiem HMC5883
Jak widać aktualizacja treści wyświetlacza odbywa się tylko przy wybraniu nowej opcji z menu. Gdy dokonamy wyboru poprzez naciśnięcie przycisku JOY_ENTER, wówczas program sprawdzi, która opcja menu była ostatnio wybrana i przejdzie do wykonania odpowiedniej funkcji:
if (!GPIO_ReadInputDataBit(JOY_PORT_ENTER, JOY_ENTER)) { switch (pozycja){ case 1: Opcja_Info(); break; case 2: Opcja_Kalibracja(); break; case 3: Opcja_Kompas(); break; case 4: Opcja_Krzywe(); break; } aktualizacja=0; }
Funkcje te wykonywane są do wciśnięcia JOY_DOWN. Pierwsza z nich to Opcja_INFO():
void Opcja_Info(void){ volatile unsigned long int i; TFTN_Clear(0x000); TFTN_WriteXY(" DEMO \0" , 5, 10,0xFFF,0x000, font2); TFTN_WriteXY(" magnetometru\0", 5, 26,0xFFF,0x000, font2); TFTN_WriteXY(" HMC588L\0" , 5, 42,0xFFF,0x000, font2); TFTN_WriteXY(" UWAGA!!!\0" , 5, 68,0xFFF,0x000, font2); TFTN_WriteXY(" Dla wiarygodnego\0", 5, 82,0xFFF,0x000, font1); TFTN_WriteXY(" pomiaru ustaw os Z\0" , 5, 90,0xFFF,0x000, font1); TFTN_WriteXY("czujnika prostopadle\0",5,98,0xFFF,0x000, font1); TFTN_WriteXY(" do ziemi oraz\0",5,106,0xFFF,0x000, font1); TFTN_WriteXY("wykonaj kalibracje!!\0",5,114,0xFFF,0x000, font1); //Czekaj na JOY_DOWN while(GPIO_ReadInputDataBit(JOY_SW_PORT, JOY_DOWN)) ; }
Ma ona za zadanie poinformować użytkownika o sposobie ustawienia i konfiguracji magnetometru, podkreślając by oś Z czujnika była ustawiona w przybliżeniu prostopadle do ziemi. Druga funkcja wybierana z opcji menu to Opcja_Kalibracja():
void Opcja_Kalibracja(void) { volatile unsigned long int i; volatile unsigned long int petla =500; //Czas kalibracji signed short x, y,z; signed short xmin=32767 ,xmax=-32768,ymin=32767,ymax=-32768; extern signed short offsetx,offsety; TFTN_Clear(0x000); TFTN_WriteXY(" KALIBRACJA \0" , 5, 10,0xFFF,0x000, font2); TFTN_WriteXY(" UWAGA!!! " , 5, 35,0xFFF,0x000, font2); TFTN_WriteXY("W czasie trwania\0" , 5, 55,0xFFF,0x000, font1); TFTN_WriteXY("sygnalu dzwiekowego\0", 5, 63,0xFFF,0x000, font1); TFTN_WriteXY("dokonaj minimalnie \0" , 5, 71,0xFFF,0x000, font1); TFTN_WriteXY("jednego obrotu \0",5,79,0xFFF,0x000, font1); TFTN_WriteXY("czujnika wzgledem osi\0",5,87,0xFFF,0x000, font1); TFTN_WriteXY("'Z' ustawionej do \0",5,95,0xFFF,0x000, font1); TFTN_WriteXY("ziemi prostopadle\0",5,103,0xFFF,0x000, font1); TFTN_WriteXY("Wcisnij JOY_ENTER\0",5,121,0xFFF,0x000, font1); //Czekaj na JOY_ENTER while(GPIO_ReadInputDataBit(JOY_PORT_ENTER, JOY_ENTER)); //Wyznaczanie minimalnych i maksymalnych wartosci pola magnetycznego na osiach X i Y //po wykonaniu co najminej jednego obrotu czujnika wokol osi Z ustawionej prostopadle //do ziemi while (petla) { HMC5883L_GetPosition(&x, &y, &z); if (xxmax) xmax=x; if (y ymax) ymax=y; petla--; //W czasie kalibracji Speaker wydaje dzwiek GPIO_WriteBit(GPIOB, GPIO_Pin_12, (BitAction)..... ....(1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_12))); } //Przesuniecie ukladu wspolrzednych tak aby //jego srodek znajdowal sie w polowie roznicy minimalnego i maksymalnego //pola magnetycznego odczytanego przez magnetometr dla osi X oraz Y offsetx=abs((xmin+xmax)*0.5); if (abs(xmin) Funkcja cyklicznie odczytuje wartość pola magnetycznego z czujnika dla każdej osi za pomocą funkcji:
void HMC5883L_GetPosition(signed short * x,signed short * y, signed short * z) { //reads 5 registers values into buffer in multiple bytes mode, buffer[0]=x, [2]=z, [3]=y unsigned char Bufor[6]={0}; unsigned int NumByteToReadN, i; //Check, if I2C is free while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); I2C_GenerateSTART(I2C1,ENABLE); //Test on EV5 and clear it while(!I2C_CheckEvent(HMC5883L_I2C, I2C_EVENT_MASTER_MODE_SELECT)); //Send HMC5883L address, set I2C master in transmiter mode I2C_Send7bitAddress(HMC5883L_I2C, HMC5883L_Addr, I2C_Direction_Transmitter); //Test on EV6 and clear it while(!I2C_CheckEvent(HMC5883L_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //Send base register address, set address autoincrement I2C_SendData(HMC5883L_I2C, 0x03); //Test on EV8 and clear it while(!I2C_CheckEvent(HMC5883L_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //Re-generate START, transmition from slave beginning I2C_GenerateSTART(HMC5883L_I2C,ENABLE); //Test on EV5 and clear it while(!I2C_CheckEvent(HMC5883L_I2C, I2C_EVENT_MASTER_MODE_SELECT)); //Send HMC5883L address, set I2C master in receiver mode I2C_Send7bitAddress(HMC5883L_I2C, HMC5883L_Addr, I2C_Direction_Receiver); //Test on EV6 and clear it while(!I2C_CheckEvent(HMC5883L_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); NumByteToReadN=6; //Read 6 consecutive registers i=0; //Current read count while(NumByteToReadN) { //Before receiving last byte, disable acknowledge and generate stop if(NumByteToReadN == 1) { I2C_AcknowledgeConfig(HMC5883L_I2C, DISABLE); I2C_GenerateSTOP(HMC5883L_I2C, ENABLE); } //Test on EV7 and clear it while(!I2C_CheckEvent(HMC5883L_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED)); //Read a byte from the HMC5883L Bufor[i] = I2C_ReceiveData(HMC5883L_I2C); i++; NumByteToReadN--; } //Enable Acknowledge for next transmission I2C_AcknowledgeConfig(HMC5883L_I2C, ENABLE); //Assign data to axis variables *x=(signed short)((Bufor[0]<<8)|Bufor[1]); *z=(signed short)((Bufor[2]<<8)|Bufor[3]); *y=(signed short)((Bufor[4]<<8)|Bufor[5]); }