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 (yymax) 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]);
}

Nordic poszerza opcje rozwojowe serii nRF54L o płytkę nRF7002 EBII do łączności Wi-Fi 6
Technologie End of Life i bezpieczeństwo sieci – wyzwania Europy związane z tzw. długiem technologicznym
Najczęstsze błędy firm przy wyborze dostawcy energii i jak ich uniknąć 



