/* *LCD * PA0(A0) = D0 * PA1(A1) = D1 * PA2(A7) = D2 * PA3(A2) = D3 * PA4(A3) = D4 * PA5(A4) = D5 * PA6(A5) = D6 * PA7(A6) = D7 * PB0(D3) = RS * PB1(D6) = E * GND = R/W * *KEYBOARD * * 1 2 3 A ...PB4(D12) OUTPUT PINS * * 4 5 6 B ...PB5(D11) * * 7 8 9 C ...PB3(D13) * * * 0 # D ...PA8(D9) * ... ... ... ... * PA9 PA10 PA11 PA12 * (D1) (D0) (D10) (D2) * * INPUT PINS * (PULL UP) * * *DAC * * 0: rampa * 1: pila * 2: trojuhelnik * 3: obdelnik * 4: sinus * * SDA: PF1(D8) * SCL: PF0(D7) * napajeni: 5V * * */ #include "stm32f0xx.h" #include "stdio.h" #include "math.h" #define setBit(reg,bit) (reg |= (1 << bit)) #define clrBit(reg,bit) (reg &= ~(1 << bit)) #define togBit(reg,bit) (reg ^= (1 << bit)) #define readBit(reg,bit) (reg & (1 << (bit))) #define LCD_SET_RS setBit(GPIOB->ODR,0) #define LCD_SET_E setBit(GPIOB->ODR,1) #define LCD_CLR_RS clrBit(GPIOB->ODR,0) #define LCD_CLR_E clrBit(GPIOB->ODR,1) #define LCD_DATA(data) GPIOA->ODR = ((GPIOA->ODR & 0xff00) + data) #define KEY_READ_COL1 readBit(GPIOA->IDR,9) #define KEY_READ_COL2 readBit(GPIOA->IDR,10) #define KEY_READ_COL3 readBit(GPIOA->IDR,11) #define KEY_READ_COL4 readBit(GPIOA->IDR,12) #define KEY_SET_ROW1 setBit(GPIOB->ODR,4) #define KEY_SET_ROW2 setBit(GPIOB->ODR,5) #define KEY_SET_ROW3 setBit(GPIOB->ODR,3) #define KEY_SET_ROW4 setBit(GPIOA->ODR,8) #define KEY_CLR_ROW1 clrBit(GPIOB->ODR,4) #define KEY_CLR_ROW2 clrBit(GPIOB->ODR,5) #define KEY_CLR_ROW3 clrBit(GPIOB->ODR,3) #define KEY_CLR_ROW4 clrBit(GPIOA->ODR,8) #define I2C_SET_SCL setBit(GPIOF->ODR,0) #define I2C_CLR_SCL clrBit(GPIOF->ODR,0) #define I2C_CLR_SDA clrBit(GPIOF->ODR,1) #define I2C_SET_SDA setBit(GPIOF->ODR,1) #define I2C_DELAY delay(0) int button = 16; int waveform = 4; int V = 300; float f = 10; int setPSC = 31250;//31250 1Hz 1562 20Hz int sinusEn = 0; int PWM = 127;//0-255 int DUTY = 50; #define BUTTON_CLR button = 16 #define WAVEFORM_RAMP waveform = 1 #define WAVEFORM_SAWTOOTH waveform = 0 #define WAVEFORM_TRIANGLE waveform = 2 #define WAVEFORM_SQUARE waveform = 3 #define WAVEFORM_SINE waveform = 4 void I2CpinInit() { //PF0 ...SCL setBit(RCC->AHBENR,22);//hodiny port F setBit(GPIOF->MODER,0);//output setBit(GPIOF->OTYPER,0);//open drain setBit(GPIOF->PUPDR,0);//pull up resistor //PF1 ...SDA setBit(RCC->AHBENR,22);//hodiny port F setBit(GPIOF->MODER,2);//output setBit(GPIOF->OTYPER,1);//open drain setBit(GPIOF->PUPDR,2);//pull up resistor } void I2C_ReadBit(void) { I2C_SET_SDA; I2C_DELAY; clrBit(GPIOF->MODER,2);//input I2C_SET_SCL; I2C_DELAY; I2C_CLR_SCL; setBit(GPIOF->MODER,2);//output I2C_DELAY; } void I2C_WriteBit(unsigned char c) { if(c > 0) I2C_SET_SDA; else I2C_CLR_SDA; I2C_DELAY; I2C_SET_SCL; I2C_DELAY; I2C_CLR_SCL; } void I2C_Init() { I2C_SET_SDA; I2C_SET_SCL; I2C_DELAY; } void I2C_Start() { I2C_SET_SCL; I2C_DELAY; I2C_SET_SDA; I2C_DELAY; I2C_CLR_SDA; I2C_DELAY; I2C_CLR_SCL; I2C_DELAY; } void I2C_Stop() { I2C_DELAY; I2C_CLR_SDA; I2C_DELAY; I2C_SET_SCL; I2C_DELAY; I2C_SET_SDA; } unsigned char I2C_Write(unsigned char c) { for (char i = 0; i < 8; i++) { I2C_WriteBit(c & 128); c <<= 1; } I2C_SET_SDA; return 0; } void I2C_Send(unsigned char addr, unsigned char reg, unsigned char data) { I2C_Start(); I2C_Write(addr); I2C_ReadBit(); // ACK I2C_Write(reg); I2C_ReadBit(); // ACK I2C_Write(data); I2C_ReadBit(); // ACK I2C_Stop(); } void TIM3Init()//cteni z ADC { setBit(RCC->APB1ENR,1); TIM3->PSC = 31250/f; // 124 pro 8 MHz 249 pro 48 MHz TIM3->ARR = 255; // 250 pro 8 MHz 750 pro 48 MHz 1Hz vystup setBit(TIM3->CR1,7);//povoleni ARR clrBit(TIM3->CR1,4);//0 upcounting,1 downcounting setBit(TIM3->CR1,0);//povoleni timeru } void rampInit() { clrBit(TIM3->CR1,4);//0 upcounting,1 downcounting clrBit(TIM3->CR1,5);//center aligned mode sinusEn = 0; TIM3->PSC = 31250/f; TIM3->CNT = 0; } void sawtoothInit() { setBit(TIM3->CR1,4);//0 upcounting,1 downcounting clrBit(TIM3->CR1,5);//center aligned mode sinusEn = 0; TIM3->PSC = 31250/f; TIM3->CNT = 0; } void triangleInit() { clrBit(TIM3->CR1,4);//0 upcounting,1 downcounting setBit(TIM3->CR1,5);//center aligned mode sinusEn = 0; TIM3->PSC = 31250/(f*2); TIM3->CNT = 0; } void squareInit() { clrBit(TIM3->CR1,4);//0 upcounting,1 downcounting clrBit(TIM3->CR1,5);//center aligned mode sinusEn = 0; TIM3->PSC = 31250/f; TIM3->CNT = 0; } void sineInit() { clrBit(TIM3->CR1,4);//0 upcounting,1 downcounting clrBit(TIM3->CR1,5);//center aligned mode sinusEn = 1; TIM3->PSC = 31250/f; TIM3->CNT = 0; } void keyInit() { setBit(RCC->AHBENR,17);//clk port A setBit(RCC->AHBENR,18);//clk port B setBit(GPIOB->MODER,8); setBit(GPIOB->MODER,10); setBit(GPIOB->MODER,6); setBit(GPIOA->MODER,16);//output pins KEY_CLR_ROW1; KEY_CLR_ROW2; KEY_CLR_ROW3; KEY_CLR_ROW4; setBit(GPIOA->PUPDR,18); setBit(GPIOA->PUPDR,20); setBit(GPIOA->PUPDR,22); setBit(GPIOA->PUPDR,24);//pull up na vstupni piny //inicializace preruseni na PA9 PA10 PA11 PA12 NVIC_SetPriority(EXTI4_15_IRQn,1); NVIC_EnableIRQ(EXTI4_15_IRQn); //SYSCFG->EXTI ...po resetu nastaven port A automaticky setBit(EXTI->IMR,9); setBit(EXTI->IMR,10); setBit(EXTI->IMR,11); setBit(EXTI->IMR,12);//maska pro piny setBit(EXTI->FTSR,9); setBit(EXTI->FTSR,10); setBit(EXTI->FTSR,11); setBit(EXTI->FTSR,12);//sebezna hrana setBit(EXTI->SWIER,9); setBit(EXTI->SWIER,10); setBit(EXTI->SWIER,11); setBit(EXTI->SWIER,12); clrBit(EXTI->PR,9); clrBit(EXTI->PR,10); clrBit(EXTI->PR,11); clrBit(EXTI->PR,12);//vymazani pending registru } void pinInit() { setBit(RCC->AHBENR,17);//CLK port A setBit(GPIOA->MODER,0); setBit(GPIOA->MODER,2); setBit(GPIOA->MODER,4); setBit(GPIOA->MODER,6); setBit(GPIOA->MODER,8); setBit(GPIOA->MODER,10); setBit(GPIOA->MODER,12); setBit(GPIOA->MODER,14);//output pin*/ setBit(RCC->AHBENR,18);//CLK port B setBit(GPIOB->MODER,0); setBit(GPIOB->MODER,2);//output pin clrBit(GPIOB->ODR,0); clrBit(GPIOB->ODR,1); } void delay(int q) { for(int i = 0; i < q; i++); } void odesli() { LCD_SET_E; delay(10); LCD_CLR_E; delay(10); } void LCDInit3V3() { LCD_CLR_RS; LCD_CLR_E; delay(1000); LCD_DATA(0b00111001);//Function set odesli(); LCD_DATA(0b00010101);//Bias set odesli(); LCD_DATA(0b01010100);//Power control odesli(); LCD_DATA(0b01101110);//Follower control odesli(); LCD_DATA(0b01111111);//Contrast control odesli(); LCD_DATA(0b00111000);//Function set odesli(); LCD_DATA(0b00001100);//Display ON/OFF odesli(); LCD_DATA(0b00000001);//Clear display odesli(); LCD_DATA(0b00000110);//Entry mode set odesli(); LCD_SET_RS; delay(1000); } void LCDText(int delka, char text[delka]) { for(int i = 0; i <= delka;i++) { LCD_DATA(text[i]); odesli(); } } void LCDWriteNumber(int a) { int a2 = a; char length = 0; do{ length++; a2 = a2/10; }while(a2 != 0); int a3[length - 1]; for(int i = 0; i < length; i++) { a3[i] = a%10; a = a/10; } for(int i = length-1; i >= 0; i--) { switch(a3[i]) { case 0: LCDText(0,"0"); break; case 1: LCDText(0,"1"); break; case 2: LCDText(0,"2"); break; case 3: LCDText(0,"3"); break; case 4: LCDText(0,"4"); break; case 5: LCDText(0,"5"); break; case 6: LCDText(0,"6"); break; case 7: LCDText(0,"7"); break; case 8: LCDText(0,"8"); break; case 9: LCDText(0,"9"); break; default: break; } } } void TIM14Init()//ochrana proti zakmytum tlacitek { setBit(RCC->APB1ENR,8); TIM14->PSC = 6000; TIM14->ARR = 100; setBit(TIM14->CR1,7);//povoleni ARR setBit(TIM14->CR1,0);//povoleni timeru clrBit(TIM14->SR,0); } int readKey() { if(readBit(TIM14->SR,0)) { if(!KEY_READ_COL1) { KEY_SET_ROW1; if(KEY_READ_COL1) { KEY_CLR_ROW1; return 1;//1 } KEY_CLR_ROW1; KEY_SET_ROW2; if(KEY_READ_COL1) { KEY_CLR_ROW2; return 4;//4 } KEY_CLR_ROW2; KEY_SET_ROW3; if(KEY_READ_COL1) { KEY_CLR_ROW3; return 7;//7 } KEY_CLR_ROW3; KEY_SET_ROW4; if(KEY_READ_COL1) { KEY_CLR_ROW4; return 10;//* } KEY_CLR_ROW4; } if(!KEY_READ_COL2) { KEY_SET_ROW1; if(KEY_READ_COL2) { KEY_CLR_ROW1; return 2;//2 } KEY_CLR_ROW1; KEY_SET_ROW2; if(KEY_READ_COL2) { KEY_CLR_ROW2; return 5;//5 } KEY_CLR_ROW2; KEY_SET_ROW3; if(KEY_READ_COL2) { KEY_CLR_ROW3; return 8;//8 } KEY_CLR_ROW3; KEY_SET_ROW4; if(KEY_READ_COL2) { KEY_CLR_ROW4; return 0;//0 } KEY_CLR_ROW4; } if(!KEY_READ_COL3) { KEY_SET_ROW1; if(KEY_READ_COL3) { KEY_CLR_ROW1; return 3;//3 } KEY_CLR_ROW1; KEY_SET_ROW2; if(KEY_READ_COL3) { KEY_CLR_ROW2; return 6;//6 } KEY_CLR_ROW2; KEY_SET_ROW3; if(KEY_READ_COL3) { KEY_CLR_ROW3; return 9;//9 } KEY_CLR_ROW3; KEY_SET_ROW4; if(KEY_READ_COL3) { KEY_CLR_ROW4; return 11;//# } KEY_CLR_ROW4; } if(!KEY_READ_COL4) { KEY_SET_ROW1; if(KEY_READ_COL4) { KEY_CLR_ROW1; return 12;//A; } KEY_CLR_ROW1; KEY_SET_ROW2; if(KEY_READ_COL4) { KEY_CLR_ROW2; return 13;//B } KEY_CLR_ROW2; KEY_SET_ROW3; if(KEY_READ_COL4) { KEY_CLR_ROW3; return 14;//C } KEY_CLR_ROW3; KEY_SET_ROW4; if(KEY_READ_COL4) { KEY_CLR_ROW4; return 15;//D } KEY_CLR_ROW4; } TIM14->CNT = 0; clrBit(TIM14->SR,0); } return 16; } void LCD_CLR_DISP() { LCD_CLR_RS; delay(1000); LCD_DATA(0b00000001);//Clear display odesli(); LCD_SET_RS; delay(1000); } void waveformSet() { int a = 1, b = 1; BUTTON_CLR; LCD_CLR_DISP(); LCDText(15,"1: Sine "); LCDText(15,"2: Square "); LCDText(15,"3: Triangle "); do{ switch(readKey()) { case 1: WAVEFORM_SINE; sineInit(); a = 0; BUTTON_CLR; break; case 2: WAVEFORM_SQUARE; delay(100000); SetDuty(); squareInit(); a = 0; BUTTON_CLR; break; case 3: LCD_CLR_DISP(); LCDText(15,"1: Triangle "); LCDText(15,"2: Sawtooth "); LCDText(15,"3: Ramp "); delay(100000); BUTTON_CLR; do{ switch(readKey()) { case 1: WAVEFORM_TRIANGLE; triangleInit(); b = 0; BUTTON_CLR; break; case 2: WAVEFORM_RAMP; rampInit(); b = 0; BUTTON_CLR; break; case 3: WAVEFORM_SAWTOOTH; sawtoothInit(); b = 0; BUTTON_CLR; break; default: b = 1; } }while(b); a = 0; BUTTON_CLR; break; default: a = 1; } }while(a); } void SetDuty() { char OK = 1; int PWM_3 = 0; do{ int a = 1, len = 0; int PWM_2[10]; LCD_CLR_DISP(); LCDText(15,"DUTY 10% - 90% "); LCDText(15,"D = "); LCDText(15," # = enter "); LCDText(15,"DUTY 10% - 90% "); LCDText(3,"D = "); BUTTON_CLR; do{ switch(readKey()) { case 0: LCDWriteNumber(0); PWM_2[len] = 0; len++; break; case 1: LCDWriteNumber(1); PWM_2[len] = 1; len++; break; case 2: LCDWriteNumber(2); PWM_2[len] = 2; len++; break; case 3: LCDWriteNumber(3); PWM_2[len] = 3; len++; break; case 4: LCDWriteNumber(4); PWM_2[len] = 4; len++; break; case 5: LCDWriteNumber(5); PWM_2[len] = 5; len++; break; case 6: LCDWriteNumber(6); PWM_2[len] = 6; len++; break; case 7: LCDWriteNumber(7); PWM_2[len] = 7; len++; break; case 8: LCDWriteNumber(8); PWM_2[len] = 8; len++; break; case 9: LCDWriteNumber(9); PWM_2[len] = 9; len++; break; case 11: a = 0; break; default: a = 1; } BUTTON_CLR; delay(100000); }while(a); switch(len) { case 2: PWM_3 = PWM_2[1] + PWM_2[0]*10; OK = 1; break; default: OK = 0; } if(PWM_3 > 90 || PWM_3 < 10) OK = 0; if(!OK) { LCD_CLR_DISP(); LCDText(15," "); LCDText(15," fatal error! "); LCDText(15," "); delay(1000000); } }while(!OK); PWM = (256/100)*PWM_3; DUTY = PWM_3; } void voltageSet() { char OK = 1; int V3 = 0, D, Dss; do{ int a = 1, len = 0; int V2[10]; LCD_CLR_DISP(); LCDText(15,"Voltage [V] = "); LCDText(15,"Vpp = "); LCDText(15," # = enter "); LCDText(15,"Voltage [V] = "); LCDText(5,"Vpp = "); BUTTON_CLR; do{ switch(readKey()) { case 0: LCDWriteNumber(0); V2[len] = 0; len++; break; case 1: LCDWriteNumber(1); V2[len] = 1; len++; break; case 2: LCDWriteNumber(2); V2[len] = 2; len++; break; case 3: LCDWriteNumber(3); V2[len] = 3; len++; break; case 4: LCDWriteNumber(4); V2[len] = 4; len++; break; case 5: LCDWriteNumber(5); V2[len] = 5; len++; break; case 6: LCDWriteNumber(6); V2[len] = 6; len++; break; case 7: LCDWriteNumber(7); V2[len] = 7; len++; break; case 8: LCDWriteNumber(8); V2[len] = 8; len++; break; case 9: LCDWriteNumber(9); V2[len] = 9; len++; break; case 11: a = 0; break; default: a = 1; } BUTTON_CLR; delay(100000); }while(a); switch(len) { case 2: V3 = V2[1] + V2[0]*10; OK = 1; break; case 3: V3 = V2[2] + V2[1]*10 + V2[0]*100; OK = 1; break; default: OK = 0; } D = 20480/V3 - 32.15; Dss = -0.1585*V3 + 152.81; if(V3 > 600 || V3 <= 80) OK = 0; if(D > 255 || D < 0) OK = 0; if(D) if(!OK) { LCD_CLR_DISP(); LCDText(15," fatal error! "); LCDText(15," Voltage range: "); LCDText(15," 81 V - 600 V "); delay(1000000); } }while(!OK); V = V3; I2C_Send(0b01011000,0b00000000,D); I2C_Send(0b01011110,0b00000000,Dss); } void frequencySet() { char OK = 1; float f3 = 0; do{ int a = 1, len = 0, decimal = 50; double f2[10]; LCD_CLR_DISP(); LCDText(15,"Frequency [Hz] ="); LCDText(15,"f = "); LCDText(15,"# = enter * = ."); LCDText(15,"Frequency [Hz] ="); LCDText(3,"f = "); BUTTON_CLR; do{ switch(readKey()) { case 0: LCDWriteNumber(0); f2[len] = 0; len++; break; case 1: LCDWriteNumber(1); f2[len] = 1; len++; break; case 2: LCDWriteNumber(2); f2[len] = 2; len++; break; case 3: LCDWriteNumber(3); f2[len] = 3; len++; break; case 4: LCDWriteNumber(4); f2[len] = 4; len++; break; case 5: LCDWriteNumber(5); f2[len] = 5; len++; break; case 6: LCDWriteNumber(6); f2[len] = 6; len++; break; case 7: LCDWriteNumber(7); f2[len] = 7; len++; break; case 8: LCDWriteNumber(8); f2[len] = 8; len++; break; case 9: LCDWriteNumber(9); f2[len] = 9; len++; break; case 10: if(decimal == 50) { LCDText(0,"."); decimal = len; } break; case 11: a = 0; break; default: a = 1; } BUTTON_CLR; delay(100000); }while(a); if(decimal > len) { switch(len) { case 1: f3 = f2[0]; OK = 1; break; case 2: f3 = f2[1] + 10*f2[0]; OK = 1; break; default: OK = 0; } } else { switch(len) { case 1: f3 = f2[0]/10; OK = 1; break; case 2: f3 = f2[1]/10 + f2[0]; OK = 1; break; case 3: f3 = f2[2]/10 + f2[1] + 10*f2[0]; OK = 1; break; default: OK = 0; } } if(f3 > 20 || f3 < 0.4) OK = 0; if((len - decimal) >= 2) OK = 0; if(!OK) { LCD_CLR_DISP(); LCDText(15," fatal error! "); LCDText(15,"frequency range:"); LCDText(15," 0.5 Hz - 20 Hz "); delay(1000000); } }while(!OK); f = f3; if(waveform != 2) TIM3->PSC = 31250/f;// 8Mhz/(256*f) = vysledna frekvence prubehu else TIM3->PSC = 31250/(f*2); } void EXTI4_15_IRQHandler() { button = readKey(); clrBit(EXTI->PR,9); clrBit(EXTI->PR,10); clrBit(EXTI->PR,11); clrBit(EXTI->PR,12); } void LCD_display() { if(button != 16) { I2C_Send(0b10010000,0b00000000,0);//posle nulu na vystup switch(readKey()) { case 12: waveformSet(); break; case 13: frequencySet(); break; case 14: voltageSet(); break; default: break; } LCD_CLR_DISP(); switch(waveform) { case 0: LCDText(15,"A: RAMP "); break; case 1: LCDText(15,"A: SAWTOOTH "); break; case 2: LCDText(15,"A: TRIANGLE "); break; case 3: LCDText(11,"A: SQUARE "); LCDWriteNumber(DUTY); LCDText(1,"% ");break; case 4: LCDText(15,"A: SINE "); break; default: break; } LCDText(6,"B: f = "); int c = f; LCDWriteNumber(c); LCDText(0,"."); LCDWriteNumber(f*10-c*10); LCDText(4," Hz "); if(c < 10) LCDText(0," "); LCDText(8,"C: Vpp = "); LCDWriteNumber(V); LCDText(1," V"); BUTTON_CLR; } } int main(void) { delay(10000);//ceka nez najede napajeni u LCD keyInit(); pinInit(); LCDInit3V3(); TIM14Init(); I2CpinInit(); TIM3Init(); button = 1;//probehne 1 cyklus vykresleni obrazovky I2C_Send(0b01011000,0b00000000,20480/V - 32.15); I2C_Send(0b01011110,0b00000000,-0.1585*V + 152.81); while (1) { LCD_display(); switch (waveform) { case 0: I2C_Send(0b10010000,0b00000000,TIM3->CNT); break;//rampa case 1: I2C_Send(0b10010000,0b00000000,TIM3->CNT); break;//pila case 2: I2C_Send(0b10010000,0b00000000,TIM3->CNT); break;//trojuhelnik case 3: if(TIM3->CNT > PWM)I2C_Send(0b10010000,0b00000000,255); else I2C_Send(0b10010000,0b00000000,0); break;//obdelnik case 4: I2C_Send(0b10010000,0b00000000,((sin(0.02455*TIM3->CNT))+1)*128); break;//sinus } } }