From 000f1cf5c50e8c78dc70e68a8afba2d00b31e24d Mon Sep 17 00:00:00 2001 From: aj Date: Tue, 3 Dec 2019 15:18:11 +0000 Subject: [PATCH] initial --- .gitignore | 4 + 7Seg Practice/7Seg.c | 100 +++++++++++ FINAL/MyDefines.h | 65 +++++++ FINAL/main.c | 112 ++++++++++++ FINALFINAL/MyDefines.h | 65 +++++++ FINALFINAL/main.c | 172 ++++++++++++++++++ HelloWorld/apples.c | 39 ++++ ISR/MyDefines.h | 43 +++++ ISR/main.c | 74 ++++++++ KeyPadSave.txt | 188 ++++++++++++++++++++ LCD Display/LCDLab.c | 82 +++++++++ LEDButton/ledbutton.c | 68 +++++++ LEDButton/ledfinal.txt | 79 +++++++++ Linked List/MyDefines.h | 43 +++++ Linked List/main.c | 98 ++++++++++ MyDefines.h | 65 +++++++ PWM DC Motor/MyDefines.h | 43 +++++ PWM DC Motor/MyDevice.h | 0 PWM DC Motor/main.c | 162 +++++++++++++++++ PinPad/MyDefines.h | 43 +++++ PinPad/pinpad.c | 134 ++++++++++++++ Report Motor Speed/MyDefines.h | 43 +++++ Report Motor Speed/main.c | 167 ++++++++++++++++++ State Machine/MyDefines.h | 43 +++++ State Machine/main.c | 188 ++++++++++++++++++++ TemplateCode_01.c | 90 ++++++++++ Timer/MyDefines.h | 62 +++++++ Timer/main.c | 118 +++++++++++++ Ultrasonic/MyDefines.h | 62 +++++++ Ultrasonic/main.c | 165 +++++++++++++++++ addserieslcd.txt | 68 +++++++ average.txt | 81 +++++++++ ezTivaLib/Defines.h | 39 ++++ ezTivaLib/ez123G.h | 14 ++ ezTivaLib/ez123GLIB.lib | Bin 0 -> 226728 bytes ezTivaLib/ezLCD.h | 72 ++++++++ ezTivaLib/ezTimer.h | 33 ++++ firstdraft.txt | 183 +++++++++++++++++++ measureFreqDutyLCD.c | 269 ++++++++++++++++++++++++++++ pwmanalyserfirstdraft.c | 297 +++++++++++++++++++++++++++++++ pwmmeasurer/MyDefines.h | 65 +++++++ pwmmeasurer/main.c | 314 +++++++++++++++++++++++++++++++++ servo/MyDefines.h | 43 +++++ servo/main.c | 88 +++++++++ 44 files changed, 4183 insertions(+) create mode 100644 .gitignore create mode 100755 7Seg Practice/7Seg.c create mode 100755 FINAL/MyDefines.h create mode 100755 FINAL/main.c create mode 100755 FINALFINAL/MyDefines.h create mode 100755 FINALFINAL/main.c create mode 100755 HelloWorld/apples.c create mode 100755 ISR/MyDefines.h create mode 100755 ISR/main.c create mode 100755 KeyPadSave.txt create mode 100755 LCD Display/LCDLab.c create mode 100755 LEDButton/ledbutton.c create mode 100755 LEDButton/ledfinal.txt create mode 100755 Linked List/MyDefines.h create mode 100755 Linked List/main.c create mode 100755 MyDefines.h create mode 100755 PWM DC Motor/MyDefines.h create mode 100755 PWM DC Motor/MyDevice.h create mode 100755 PWM DC Motor/main.c create mode 100755 PinPad/MyDefines.h create mode 100755 PinPad/pinpad.c create mode 100755 Report Motor Speed/MyDefines.h create mode 100755 Report Motor Speed/main.c create mode 100755 State Machine/MyDefines.h create mode 100755 State Machine/main.c create mode 100755 TemplateCode_01.c create mode 100755 Timer/MyDefines.h create mode 100755 Timer/main.c create mode 100755 Ultrasonic/MyDefines.h create mode 100755 Ultrasonic/main.c create mode 100755 addserieslcd.txt create mode 100755 average.txt create mode 100755 ezTivaLib/Defines.h create mode 100755 ezTivaLib/ez123G.h create mode 100755 ezTivaLib/ez123GLIB.lib create mode 100755 ezTivaLib/ezLCD.h create mode 100755 ezTivaLib/ezTimer.h create mode 100755 firstdraft.txt create mode 100755 measureFreqDutyLCD.c create mode 100755 pwmanalyserfirstdraft.c create mode 100755 pwmmeasurer/MyDefines.h create mode 100755 pwmmeasurer/main.c create mode 100755 servo/MyDefines.h create mode 100755 servo/main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fe9336e --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.uvoptx +*.uvprojx +*.uvguix.andy_ +*.scvd diff --git a/7Seg Practice/7Seg.c b/7Seg Practice/7Seg.c new file mode 100755 index 0000000..09d592c --- /dev/null +++ b/7Seg Practice/7Seg.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include + +#include "TM4C123GH6PM.h" +void DelayMs(int s); +void initGPIO(void); + +int main(void) +{ + initGPIO(); + + int numbers[16] = { + 0x3F, + 0x06, + 0x5B, + 0x4F, + 0x66, + 0x6D, + 0x7D, + 0x07, + 0x7F, + 0x6F, + 0x77, + 0x7C, + 0x39, + 0x5E, + 0x79, + 0x71 + }; + + int a = 0; + GPIOA -> DATA = (numbers[a] << 2) & 0x1C; + GPIOC -> DATA = (numbers[a] << 1) & 0xF0; + + bool currSW2state; + bool prevSW2state = 0; + + for(;;){ + + currSW2state = !(GPIOF -> DATA & 0x01); + + if(currSW2state && !prevSW2state){ + a++; + if(a == 16) a = 0; + GPIOA -> DATA = (numbers[a] << 2) & 0x1C; + GPIOC -> DATA = (numbers[a] << 1) & 0xF0; + } + + if(!(GPIOF -> DATA & 0x10)){ + a = 0; + GPIOA -> DATA = (numbers[a] << 2) & 0x1C; + GPIOC -> DATA = (numbers[a] << 1) & 0xF0; + } + + prevSW2state = currSW2state; + + } +} + +void initGPIO(){ + // GPIO Configuration + // 1. Enable Clock on Port F (SYSCTL_RCGCGPIO) + SYSCTL->RCGCGPIO = 0x2D; + // allow time for clock to stabilize (SYSCTL_PRGPIO) + while((SYSCTL->PRGPIO & 0x2D) != 0x2D){}; + // 2. Unlock GIOD[7] and GPIOF[0] on TM4C123G (GPIOn->LOCK and GPIOn->CR) + GPIOF->LOCK = 0x4C4F434B; + GPIOD->LOCK = 0x4C4F434B; + GPIOF->CR |= 0x01; + GPIOD->CR |= 0x80; + // 3. Clear AMSEL to disable analog + //GPIOF->AMSEL = 0x00; + //GPIOC->AMSEL = 0x00; + //GPIOA->AMSEL = 0x00; + //GPIOD->AMSEL = 0x00; + // 4. Config PCTL to select GPIO + //GPIOF->PCTL = 0x00; + //GPIOA->PCTL = 0x00; + //GPIOC->PCTL = 0x00; + //GPIOD->PCTL = 0x00; + // 5. Set DIR to 0 for input, 1 for output + GPIOA->DIR |= 0x1C; + GPIOC->DIR |= 0xF0; + GPIOD->DIR |= 0x80; + GPIOF->DIR = 0x0E; // PF3,PF2,PF1 for Output + // 6. Clear AFSEL bits to 0 to select regular I/O + //GPIOF->AFSEL = 0x00; + //GPIOA->AFSEL = 0x00; + //GPIOC->AFSEL = 0x00; + //GPIOD->AFSEL = 0x00; + // 7. Set PUR bits to 1 to enable internal pull-up resistor + GPIOF->PUR = 0x11; + // 8. Set DEN bits to 1 to enable data pins + GPIOA->DEN = 0x1C; + GPIOC->DEN |= 0xF0; + GPIOD->DEN = 0x80; + GPIOF->DEN = 0x1F; // Enable all digital pins on PortF (PF3,PF2,PF1,PF0) +} diff --git a/FINAL/MyDefines.h b/FINAL/MyDefines.h new file mode 100755 index 0000000..146c609 --- /dev/null +++ b/FINAL/MyDefines.h @@ -0,0 +1,65 @@ +#ifndef __MYDEFINES_H +#define __MYDEFINES_H + +#define _PIN0 0x01 +#define _PIN1 0x02 +#define _PIN2 0x04 +#define _PIN3 0x08 +#define _PIN4 0x10 +#define _PIN5 0x20 +#define _PIN6 0x40 +#define _PIN7 0x80 + +#define _PORTA 0x0001 +#define _PORTB 0x0002 +#define _PORTC 0x0004 +#define _PORTD 0x0008 +#define _PORTE 0x0010 +#define _PORTF 0x0020 + + +#define _PWM_MODULE0 0x01 +#define _PWM_MODULE1 0x02 + +#define _PWM0 0x01 +#define _PWM1 0x02 +#define _PWM2 0x04 +#define _PWM3 0x08 +#define _PWM4 0x10 +#define _PWM5 0x20 +#define _PWM6 0x40 +#define _PWM7 0x80 + +#define _PWMDIV_2 0x0 +#define _PWMDIV_4 0x1 +#define _PWMDIV_8 0x2 +#define _PWMDIV_16 0x3 +#define _PWMDIV_32 0x4 +#define _PWMDIV_64 0x5 + +#define _PWM_LEFT_ALIG_CMPAD ((0x02 << 6) | (0x03 << 2)) +#define _PWM_LEFT_ALIG_CMPBD ((0x02 << 10) | (0x03 << 2)) + +#define _PWM_RIGHT_ALIG_CMPAD ((0x03 << 6) | (0x02 << 2)) +#define _PWM_RIGHT_ALIG_CMPBD ((0x03 << 10) | (0x02 << 2)) + +#define _TIMER0 0x01 +#define _TIMER1 0x02 +#define _TIMER2 0x04 +#define _TIMER3 0x08 +#define _TIMER4 0x10 +#define _TIMER5 0x20 +#define _TIMER6 0x40 +#define _TIMER7 0x80 + +#define _TIMERA_ENABLE (1 << 0) +#define _TIMERB_ENABLE (1 << 8) +#define _TIMERA_COUNTUP (1 << 4) +#define _TIMERA_COUNTDOWN (0 << 4) +#define _TIMERA_CAPTURE 0x03 +#define _TIMERA_EDGE_TIME (1 << 2) +#define _TIMERA_POSITIVE_EDGE 0 +#define _TIMERA_NEGATIVE_EDGE (1 << 2) +#define _TIMERA_BOTH_EDGES (3 << 2) + +#endif \ No newline at end of file diff --git a/FINAL/main.c b/FINAL/main.c new file mode 100755 index 0000000..c1db107 --- /dev/null +++ b/FINAL/main.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include + +#include +//#include RCGCGPIO = _PORTC|_PORTD|_PORTF; + // allow time for clock to stabilize + while((SYSCTL->PRGPIO & (_PORTC|_PORTD|_PORTF)) != (_PORTC|_PORTD|_PORTF)){}; + + // 2. Unlock GPIO + GPIOF->LOCK = 0x4C4F434B; + GPIOF->CR |= 0x01; + // 3. Clear AMSEL to disable analog + // 4. Config PCTL to select GPIO + GPIOC->PCTL= 0x000000; + // 5. Set DIR to 0 for input, 1 for output + GPIOC -> DIR |= _PIN5; + GPIOD -> DIR = 0x0; + GPIOF -> DIR = _PIN0|_PIN1|_PIN3; + // 6. Enable AFSEL bits to 1 + GPIOC -> AFSEL |= _PIN5; + // 7. Set PUE bits to 1 to enable internal pull-up + GPIOD -> PDR= _PIN6; + GPIOF -> PUR= _PIN0; + // 8. Set DEN bits to 1 to enable data pins + GPIOF->DEN= _PIN1 | _PIN4 | _PIN2; +} +//------------------------------------------------------------------------------ diff --git a/FINALFINAL/MyDefines.h b/FINALFINAL/MyDefines.h new file mode 100755 index 0000000..146c609 --- /dev/null +++ b/FINALFINAL/MyDefines.h @@ -0,0 +1,65 @@ +#ifndef __MYDEFINES_H +#define __MYDEFINES_H + +#define _PIN0 0x01 +#define _PIN1 0x02 +#define _PIN2 0x04 +#define _PIN3 0x08 +#define _PIN4 0x10 +#define _PIN5 0x20 +#define _PIN6 0x40 +#define _PIN7 0x80 + +#define _PORTA 0x0001 +#define _PORTB 0x0002 +#define _PORTC 0x0004 +#define _PORTD 0x0008 +#define _PORTE 0x0010 +#define _PORTF 0x0020 + + +#define _PWM_MODULE0 0x01 +#define _PWM_MODULE1 0x02 + +#define _PWM0 0x01 +#define _PWM1 0x02 +#define _PWM2 0x04 +#define _PWM3 0x08 +#define _PWM4 0x10 +#define _PWM5 0x20 +#define _PWM6 0x40 +#define _PWM7 0x80 + +#define _PWMDIV_2 0x0 +#define _PWMDIV_4 0x1 +#define _PWMDIV_8 0x2 +#define _PWMDIV_16 0x3 +#define _PWMDIV_32 0x4 +#define _PWMDIV_64 0x5 + +#define _PWM_LEFT_ALIG_CMPAD ((0x02 << 6) | (0x03 << 2)) +#define _PWM_LEFT_ALIG_CMPBD ((0x02 << 10) | (0x03 << 2)) + +#define _PWM_RIGHT_ALIG_CMPAD ((0x03 << 6) | (0x02 << 2)) +#define _PWM_RIGHT_ALIG_CMPBD ((0x03 << 10) | (0x02 << 2)) + +#define _TIMER0 0x01 +#define _TIMER1 0x02 +#define _TIMER2 0x04 +#define _TIMER3 0x08 +#define _TIMER4 0x10 +#define _TIMER5 0x20 +#define _TIMER6 0x40 +#define _TIMER7 0x80 + +#define _TIMERA_ENABLE (1 << 0) +#define _TIMERB_ENABLE (1 << 8) +#define _TIMERA_COUNTUP (1 << 4) +#define _TIMERA_COUNTDOWN (0 << 4) +#define _TIMERA_CAPTURE 0x03 +#define _TIMERA_EDGE_TIME (1 << 2) +#define _TIMERA_POSITIVE_EDGE 0 +#define _TIMERA_NEGATIVE_EDGE (1 << 2) +#define _TIMERA_BOTH_EDGES (3 << 2) + +#endif \ No newline at end of file diff --git a/FINALFINAL/main.c b/FINALFINAL/main.c new file mode 100755 index 0000000..e427161 --- /dev/null +++ b/FINALFINAL/main.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include + +#include +//#include _3_CMPB = cmp_1_0m; + if(SW1) state = S_0; + if(SW2) state = S_IDLE; + + *pLed1 = 0x0; + *pLed2 = 0x0; + + break; + case S_0: + PWM0->_3_CMPB = cmp_1_0m; + if(SW1) state = S_1; + if(SW2) state = S_2; + *pLed2 = 0x0; + + if(i%2 == 0){ //200ms delay + //blink led1 + if(!(*pLed1 & _PIN1)) *pLed1 = 0xFF; + else *pLed1 = 0x00; + } + + break; + case S_1: + PWM0->_3_CMPB = cmp_1_5m; + if(SW1) state = S_2; + if(SW2) state = S_IDLE; + + if(i%2 == 0){ //200ms delay + //blink led1 and led2 + if(!(*pLed1 & _PIN1)) *pLed1 = 0xFF; + else *pLed1 = 0x00; + if(!(*pLed2 & _PIN3)) *pLed2 = 0xFF; + else *pLed2 = 0x00; + } + + break; + case S_2: + PWM0->_3_CMPB = cmp_2_0m; + if(SW1) state = S_IDLE; + if(SW2) state = S_0; + *pLed1 = 0x0; + + if(i%2 == 0){ //200ms delay + //blink led2 + if(!(*pLed2 & _PIN3)) *pLed2 = 0xFF; + else *pLed2 = 0x00; + } + + break; + } + i++; + timer_waitMillis(100); // This is the only delay function in the code. + } +} +//------------------------------------------------------------------------------ +void Setup_PWM(void) +{ + // 1. Enable Clock for PWM Module 1 + SYSCTL->RCGCPWM |= _PWM_MODULE0; + while((SYSCTL->PRPWM & _PWM_MODULE0)==0){}; + // 2. Enable and Setup Clock Divider for PWM + SYSCTL->RCC |= (1 << 20); // RCC[20]=1:USEPWMDIV + SYSCTL->RCC &= ~0x000E0000; // RCC[19:17]=000 PWMDIV + SYSCTL->RCC |= (_PWMDIV_32 << 17); // RCC[19:17]=0x04 divider=/32 + // 3. Disable PWM Generator 2 + PWM0->_3_CTL &= ~0x01; // Disable PWM Generator 2 + // 4. Config LOAD, CMPn, GENn values + PWM0->_3_LOAD = 25000; // GEN 3 B PWM 7 PF3 MOTOR + PWM0->_3_CMPB = 23750; + PWM0->_3_GENB = _PWM_LEFT_ALIG_CMPBD;//0x080C + // 5. Enable PWM Generator 3 + PWM0->_3_CTL |= 0x01; + // 6. Enable PWM7 Output + PWM0 -> ENABLE |= _PWM7; +} +//------------------------------------------------------------------------------ +void Setup_GPIO(void) +{ + // Config for GPIO + // 1. Enable Clock on GPIOF + SYSCTL->RCGCGPIO = _PORTC|_PORTD|_PORTF; + // allow time for clock to stabilize + while((SYSCTL->PRGPIO & (_PORTC|_PORTD|_PORTF)) != (_PORTC|_PORTD|_PORTF)){}; + // 2. Unlock GPIO + GPIOF->LOCK = 0x4C4F434B; + GPIOF->CR |= 0x01; + // 3. Clear AMSEL to disable analog + // 4. Config PCTL to select GPIO + GPIOC->PCTL |= 0x400000; //M0PWM7 GEN3 + // 5. Set DIR to 0 for input, 1 for output + GPIOC -> DIR |= _PIN5; + GPIOD -> DIR = 0x0; + GPIOF -> DIR |= _PIN1|_PIN3; + // 6. Enable AFSEL bits to 1 + GPIOC -> AFSEL |= _PIN5; + GPIOD -> AFSEL = 0x0; + GPIOF -> AFSEL = 0x0; + // 7. Set PUE bits to 1 to enable internal pull-up + GPIOD -> PDR |= _PIN6; + GPIOF -> PUR |= _PIN0; + // 8. Set DEN bits to 1 to enable data pins + GPIOC->DEN |= _PIN5; + GPIOD->DEN |= _PIN6; + GPIOF->DEN |= _PIN0 | _PIN1 | _PIN3; +} +//------------------------------------------------------------------------------ diff --git a/HelloWorld/apples.c b/HelloWorld/apples.c new file mode 100755 index 0000000..bd5dd73 --- /dev/null +++ b/HelloWorld/apples.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +#include "TM4C123GH6PM.h" +void DelayMs(int s); +void Delay(int t); + +int main(void) +{ + + // GPIO Configuration + // 1. Enable Clock on GPIOF[3:1] (SYSCTL_RCGCGPIO) + SYSCTL->RCGCGPIO = 0x20; + // allow time for clock to stabilize (SYSCTL_PRGPIO) + while((SYSCTL->PRGPIO & 0x20) != 0x20){}; + // 2. Unlock GPIOC[3:0], GIOD[7] and GPIOF[0] on TM4C123G (GPIOn->LOCK and GPIOn->CR) NOT USING + // 3. Clear AMSEL to disable analog + GPIOF->AMSEL = 0x00; + // 4. Config PCTL to select GPIO + GPIOF->PCTL = 0x0000; + //or + //GPIOF->PCTL &= 0xFFF00FFF; + // 5. Set DIR to 0 for input, 1 for output + GPIOF->DIR = 0x08; // PF3,PF2,PF1 for Output + // 6. Enable AFSEL bits to 1 + GPIOF->AFSEL = 0x00; + // 7. Set PUR bits to 1 to enable internal pull-up + GPIOF->PUR = 0x10; + // 8. Set DEN bits to 1 to enable data pins + GPIOF->DEN = 0x0E; // Enable digital pin on PF3,PF2,PF1 + + int sample = GPIOF -> DATA; + sample |= 0x0E; + //sample |= 0x08; + GPIOF->DATA = sample; + +} \ No newline at end of file diff --git a/ISR/MyDefines.h b/ISR/MyDefines.h new file mode 100755 index 0000000..fb99053 --- /dev/null +++ b/ISR/MyDefines.h @@ -0,0 +1,43 @@ +#ifndef __MYDEFINES_H +#define __MYDEFINES_H + +#define _PIN0 0x01 +#define _PIN1 0x02 +#define _PIN2 0x04 +#define _PIN3 0x08 +#define _PIN4 0x10 +#define _PIN5 0x20 +#define _PIN6 0x40 +#define _PIN7 0x80 + +#define _PORTA 0x0001 +#define _PORTB 0x0002 +#define _PORTC 0x0004 +#define _PORTD 0x0008 +#define _PORTE 0x0010 +#define _PORTF 0x0020 + + +#define _PWM_MODULE0 0x01 +#define _PWM_MODULE1 0x02 + +#define _PWM0 0x01 +#define _PWM1 0x02 +#define _PWM2 0x04 +#define _PWM3 0x08 +#define _PWM4 0x10 +#define _PWM5 0x20 +#define _PWM6 0x40 +#define _PWM7 0x80 + +#define _PWMDIV_2 0x0 +#define _PWMDIV_4 0x1 +#define _PWMDIV_8 0x2 +#define _PWMDIV_16 0x3 +#define _PWMDIV_32 0x4 +#define _PWMDIV_64 0x5 + +#define _PWM_LEFT_ALIG_CMPAD ((0x02 << 6) | (0x03 << 2)) +#define _PWM_LEFT_ALIG_CMPBD ((0x02 << 10) | (0x03 << 2)) + +#endif \ No newline at end of file diff --git a/ISR/main.c b/ISR/main.c new file mode 100755 index 0000000..b71bc35 --- /dev/null +++ b/ISR/main.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include "MyDefines.h" + +#include "TM4C123GH6PM.h" + +void SetupGPIO(void); +void SetupGPIOIRQ(void); +void GPIOF_Handler(void); + +int main() +{ + SetupGPIO(); + SetupGPIOIRQ(); + + while(1){ + + } +} + +void SetupGPIO(void){ + + // Config for GPIO + // 1. Enable Clock on GPIOF + SYSCTL->RCGCGPIO = _PORTF; + // allow time for clock to stabilize + while((SYSCTL->PRGPIO & _PORTF) != _PORTF){}; + // 2. Unlock GPIO + // 3. Clear AMSEL to disable analog + GPIOF -> AMSEL = 0x0; + // 4. Config PCTL to select GPIO + GPIOF -> PCTL = 0x0; + // 5. Set DIR to 0 for input, 1 for output + GPIOF -> DIR = _PIN1; + // 6. Enable AFSEL bits to 1 + GPIOF -> AFSEL = 0x0; + // 7. Set PUE bits to 1 to enable internal pull-up + GPIOF -> PUR = _PIN4; + // 8. Set DEN bits to 1 to enable data pins + GPIOF -> DEN = _PIN4|_PIN1; +} + +void SetupGPIOIRQ() +{ + uint32_t n, r, m, r2; + // 1. Disable IRQ in GPIOIM register + GPIOF->IM &= ~(_PIN4); + // 2. Configure IRQ Type (0=edge, 1=level) in the GPIOIS register + GPIOF->IS &= ~(_PIN4); + // 3. Configure GPIOIBE (0=single edge, 1=both edge), + // GPIOIEV (0=low level or falling edge, 1=high level or rising edge) + GPIOF->IBE &= ~(_PIN4); + GPIOF->IEV &= ~(_PIN4); + // 4. Clear the GPIORIS register + GPIOF->ICR |= _PIN4; + // 5. Enable IRQ in the GPIOIM register + GPIOF->IM |= _PIN4; + // 6. Set priority in the NVIC + n = 30 / 4; + r = 21; // remainder:0 -> r = 5, :1-> r=13, :2-> r=21, :3-> r=29 + m = 30 / 32; r2 = 30 % 32; + NVIC->IP[n] |= (3 << r); + // 7. Enable IRQ in the NVIC + NVIC->ISER[m] |= (1 << r2); +} + +uint32_t* pn1 = (uint32_t*)(((char*)GPIOF) + (_PIN1 << 2)); +void GPIOF_Handler(){ + GPIOF->ICR |= _PIN4; //clear interrupt flag + *pn1 ^= _PIN1; + +} \ No newline at end of file diff --git a/KeyPadSave.txt b/KeyPadSave.txt new file mode 100755 index 0000000..4b3f979 --- /dev/null +++ b/KeyPadSave.txt @@ -0,0 +1,188 @@ +#include +#include +#include +#include + +#include "TM4C123GH6PM.h" +#include "ez123G.h" +#include "MyDefines.h" + +char str[100]; +char ReadKeyPad2(); +char ReadKeyPad1(); +char ReadKeyPad(); + +int main(void) +{ + PEZOBJ_LCD lcd; + uint16_t i = 0; + + // GPIO Initialization and Configuration + // 1. Enable Clock on GPIOs + SYSCTL->RCGCGPIO |= 0x1B; + // allow time for clock to stabilize + while ((SYSCTL->PRGPIO & 0x1B) != 0x1B) {}; + // 2. Unlock PD7 and/or PF0 for TM4C 123G + // 3. Config AMSEL to disable analog function + // 4. Config PCTL to select 0-GPIO + // 5. Set AFSEL bits to 0 + // 6. Set DIR to 0 for input, 1 for output + + GPIOA -> DIR = 0x00; + GPIOB -> DIR = 0x03; + GPIOD -> DIR = 0x0F; + GPIOE -> DIR = 0x3E; + + // 7. Set PUR/PDR/ODR bits to 1 to enable internal pull-up/-down resistir and/or open-drain + GPIOB -> ODR = 0x03; + GPIOE -> ODR = 0x30; + GPIOA -> PUR = 0xE0; + GPIOB -> PUR = 0x10; + + // 8. Set DEN bits to 1 to enable all + GPIOA -> DEN = 0xE0; + GPIOB -> DEN = 0x13; + GPIOD -> DEN = 0x0F; + GPIOE -> DEN = 0x3E; + + + lcd = ezLCD_Create(); + ezLCD_Connect_DataPort(lcd, GPIOD, PIN_3_0); + ezLCD_Connect_ENPin(lcd, GPIOE, PIN1); + ezLCD_Connect_RSPin(lcd, GPIOE, PIN2); + ezLCD_Connect_RWPin(lcd, GPIOE, PIN3); + + ezLCD_Start(lcd); + ezLCD_ClearDisplay(lcd); + + char ch; + while(1){ + ch = ReadKeyPad(); + + if (ch == '*'){ + i *= 100; + ezLCD_ClearDisplay(lcd); + } + if (ch == '#') i = 0; + if (ch >='0' && ch <= '9') i = i*10 + ch - '0'; + + sprintf(str, "%c ", ch); + ezLCD_Position(lcd, 0, 0); + ezLCD_PrintString(lcd, str); + + timer_waitMillis(100); + } +} +//-------------------------------------------------------------- +char KeyPad[4][4]={ + {'1','2','3','A'}, + {'4','5','6','B'}, + {'7','8','9','C'}, + {'*','0','#','D'}}; + +char ReadKeyPad1() +{ + + GPIOB -> DATA |= 0x03; + GPIOE -> DATA |= 0x30; + //GPIOB -> DATA |= 0x01; + GPIOB -> DATA &= ~0x02; + //GPIOE -> DATA |= 0x10; + //GPIOE -> DATA &= ~0x20; + + timer_waitMillis(10); + + if(!(GPIOB -> DATA & 0x10)) return KeyPad[1][0]; + if(!(GPIOA -> DATA & 0x20)) return KeyPad[1][1]; + if(!(GPIOA -> DATA & 0x40)) return KeyPad[1][2]; + if(!(GPIOA -> DATA & 0x80)) return KeyPad[1][3]; + + return 0x0; +} + +char ReadKeyPad2() +{ + int row; + GPIOB -> DATA |= 0x03; + GPIOE -> DATA |= 0x30; + for(row = 0; row < 4; row++){ + switch(row){ + case 0: + GPIOB -> DATA &= ~0x01; + timer_waitMillis(10); + if(!(GPIOB -> DATA & 0x10)) return KeyPad[0][0]; + if(!(GPIOA -> DATA & 0x20)) return KeyPad[0][1]; + if(!(GPIOA -> DATA & 0x40)) return KeyPad[0][2]; + if(!(GPIOA -> DATA & 0x80)) return KeyPad[0][3]; + break; + case 1: + GPIOB -> DATA |= 0x01; + GPIOB -> DATA &= ~0x02; + timer_waitMillis(10); + if(!(GPIOB -> DATA & 0x10)) return KeyPad[1][0]; + if(!(GPIOA -> DATA & 0x20)) return KeyPad[1][1]; + if(!(GPIOA -> DATA & 0x40)) return KeyPad[1][2]; + if(!(GPIOA -> DATA & 0x80)) return KeyPad[1][3]; + break; + case 2: + GPIOB -> DATA |= 0x02; + GPIOE -> DATA &= ~0x10; + timer_waitMillis(10); + if(!(GPIOB -> DATA & 0x10)) return KeyPad[2][0]; + if(!(GPIOA -> DATA & 0x20)) return KeyPad[2][1]; + if(!(GPIOA -> DATA & 0x40)) return KeyPad[2][2]; + if(!(GPIOA -> DATA & 0x80)) return KeyPad[2][3]; + break; + case 3: + GPIOE -> DATA |= 0x10; + GPIOE -> DATA &= ~0x20; + timer_waitMillis(10); + if(!(GPIOB -> DATA & 0x10)) return KeyPad[3][0]; + if(!(GPIOA -> DATA & 0x20)) return KeyPad[3][1]; + if(!(GPIOA -> DATA & 0x40)) return KeyPad[3][2]; + if(!(GPIOA -> DATA & 0x80)) return KeyPad[3][3]; + break; + } + + row++; + } + + return 0x0; +} + +char ReadKeyPad() +{ + int row; + GPIOB -> DATA |= 0x03; + GPIOE -> DATA |= 0x30; + for(row = 0; row < 4; row++){ + switch(row){ + case 0: + GPIOB -> DATA &= ~0x01; + break; + case 1: + GPIOB -> DATA |= 0x01; + GPIOB -> DATA &= ~0x02; + break; + case 2: + GPIOB -> DATA |= 0x02; + GPIOE -> DATA &= ~0x10; + break; + case 3: + GPIOE -> DATA |= 0x10; + GPIOE -> DATA &= ~0x20; + break; + } + + timer_waitMillis(10); + + if(!(GPIOB -> DATA & 0x10)) return KeyPad[row][0]; + if(!(GPIOA -> DATA & 0x20)) return KeyPad[row][1]; + if(!(GPIOA -> DATA & 0x40)) return KeyPad[row][2]; + if(!(GPIOA -> DATA & 0x80)) return KeyPad[row][3]; + + row++; + } + + return 0x0; +} \ No newline at end of file diff --git a/LCD Display/LCDLab.c b/LCD Display/LCDLab.c new file mode 100755 index 0000000..f2c3699 --- /dev/null +++ b/LCD Display/LCDLab.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include + +#include "TM4C123GH6PM.h" +#include "ez123G.h" + +char str[100]; + +int main(void) +{ + PEZOBJ_LCD lcd; + uint16_t i = 0; + int array[]= {10, 35, 65, 43, 32, 86, 44, 9, 18}; + + // Enable GPIOD[3:0] and GPIOE[3:1] + // Config for GPIOD and GPIOE + // 1. Enable Clock on GPIOs + SYSCTL->RCGCGPIO |= 0x18; + // allow time for clock to stabilize + while ((SYSCTL->PRGPIO & 0x18) != 0x18) {}; + // 2. Unlock PD7 + GPIOD->LOCK = 0x4C4F434B; + GPIOD->CR |= 0x80; + + // 3. Config AMSEL to disable analog function + GPIOD -> AMSEL = 0x00; + GPIOE -> AMSEL = 0x00; + // 4. Config PCTL to select GPIO + GPIOD -> PCTL = 0x00; + GPIOE -> PCTL = 0x00; + // 5. Set DIR to 0 for input, 1 for output + GPIOD -> DIR |= 0x0F; + GPIOE -> DIR |= 0x0E; + + // 6. Set AFSEL bits to 0 + GPIOD -> AFSEL = 0x00; + GPIOE -> AFSEL = 0x00; + // 7. Set PUE bits to 1 to enable internal pull-up (Skipped) + // 8. Set DEN bits to 1 to enable data pins + GPIOD -> DEN |= 0x0F; + GPIOE -> DEN |= 0x0E; + + + lcd = ezLCD_Create(); + ezLCD_Connect_DataPort(lcd, GPIOD, PIN_3_0); + ezLCD_Connect_ENPin(lcd, GPIOE, PIN1); + ezLCD_Connect_RSPin(lcd, GPIOE, PIN2); + ezLCD_Connect_RWPin(lcd, GPIOE, PIN3); + + ezLCD_Start(lcd); + ezLCD_LoadVerticalBargraphFonts(lcd); + + ezLCD_ClearDisplay(lcd); + + int j = 0; + float a; + int s = 0, M = array[0], m = array[0]; + int total = 0; + while(j <= 8){ + ezLCD_ClearDisplay(lcd); + s += array[j]; + if(array[j] > M) M = array[j]; + if(array[j] < m) m = array[j]; + a = s / (j + 1); + ezLCD_Position(lcd, 0, 0); + sprintf(str, "S=%d", s); + ezLCD_PrintString(lcd, str); + ezLCD_Position(lcd, 0, 8); + sprintf(str, "M=%d", M); + ezLCD_PrintString(lcd, str); + ezLCD_Position(lcd, 1, 0); + sprintf(str, "A=%.2f", a); + ezLCD_PrintString(lcd, str); + ezLCD_Position(lcd, 1, 8); + sprintf(str, "m=%d", m); + ezLCD_PrintString(lcd, str); + timer_waitMillis(500); + j++; + } +} \ No newline at end of file diff --git a/LEDButton/ledbutton.c b/LEDButton/ledbutton.c new file mode 100755 index 0000000..bb0d77d --- /dev/null +++ b/LEDButton/ledbutton.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include + +#include "TM4C123GH6PM.h" +void initGPIO(void); +void Delay(int t); + +int main(void) +{ + initGPIO(); + int sample = 0x00; + + for(;;){ + + sample = GPIOF -> DATA; + + //SWITCH ONE ON + if(!(sample & 0x10)){ + GPIOF -> DATA |= 0x02; + Delay(2000); + GPIOF -> DATA &= 0xFD; + } + + //SWITCH TWO ON + if(!(sample & 0x01)){ + GPIOF -> DATA |= 0x08; + Delay(2000); + GPIOF -> DATA &= 0xF7; + } + + } +} + +void initGPIO(void){ + + // GPIO Configuration + // 1. Enable Clock on GPIOF[3:1] (SYSCTL_RCGCGPIO) + SYSCTL->RCGCGPIO = 0x20; + // allow time for clock to stabilize (SYSCTL_PRGPIO) + while((SYSCTL->PRGPIO & 0x20) != 0x20){}; + // 2. Unlock GPIOC[3:0], GIOD[7] and GPIOF[0] on TM4C123G (GPIOn->LOCK and GPIOn->CR) NOT USING + GPIOF->LOCK = 0x4C4F434B; + GPIOF->CR |= 0x01; + // 3. Clear AMSEL to disable analog + GPIOF->AMSEL = 0x00; + // 4. Config PCTL to select GPIO + GPIOF->PCTL = 0x0000; + //or + //GPIOF->PCTL &= 0xFFF00FFF; + // 5. Set DIR to 0 for input, 1 for output + GPIOF->DIR = 0x0E; // PF3,PF2,PF1 for Output + // 6. Enable AFSEL bits to 1 + GPIOF->AFSEL = 0x00; + // 7. Set PUR bits to 1 to enable internal pull-up + GPIOF->PUR = 0x11; + // 8. Set DEN bits to 1 to enable data pins + GPIOF->DEN = 0x1F; // Enable digital pin on PF3,PF2,PF1 +} + +void Delay(int t) +{ + volatile int i, j; + for (i = 0; i < t; i++) + for (j = 0; j < 3180; j++) + {}; +} diff --git a/LEDButton/ledfinal.txt b/LEDButton/ledfinal.txt new file mode 100755 index 0000000..e5cff86 --- /dev/null +++ b/LEDButton/ledfinal.txt @@ -0,0 +1,79 @@ +#include +#include +#include +#include + +#include "TM4C123GH6PM.h" +void DelayMs(int s); +void Delay(int t); + +int main(void) +{ + + // GPIO Configuration + // 1. Enable Clock on GPIOF[3:1] (SYSCTL_RCGCGPIO) + SYSCTL->RCGCGPIO = 0x20; + // allow time for clock to stabilize (SYSCTL_PRGPIO) + while((SYSCTL->PRGPIO & 0x20) != 0x20){}; + // 2. Unlock GPIOC[3:0], GIOD[7] and GPIOF[0] on TM4C123G (GPIOn->LOCK and GPIOn->CR) NOT USING + GPIOF->LOCK = 0x4C4F434B; + GPIOF->CR |= 0x01; + // 3. Clear AMSEL to disable analog + GPIOF->AMSEL = 0x00; + // 4. Config PCTL to select GPIO + GPIOF->PCTL = 0x0000; + //or + //GPIOF->PCTL &= 0xFFF00FFF; + // 5. Set DIR to 0 for input, 1 for output + GPIOF->DIR = 0x0E; // PF3,PF2,PF1 for Output + // 6. Enable AFSEL bits to 1 + GPIOF->AFSEL = 0x00; + // 7. Set PUR bits to 1 to enable internal pull-up + GPIOF->PUR = 0x11; + // 8. Set DEN bits to 1 to enable data pins + GPIOF->DEN = 0x1F; // Enable digital pin on PF3,PF2,PF1 + + + + int sample = 0x00; + int led = 0x00; + + for(;;){ + + sample = GPIOF -> DATA; + + //SWITCH ONE ON + if(!(sample & 0x10)){ + led = GPIOF -> DATA; + led |= 0x02; + GPIOF -> DATA = led; + Delay(60); + led = GPIOF -> DATA; + led &= 0xFD; + GPIOF -> DATA = led; + } + + + //SWITCH TWO ON + if(!(sample & 0x01)){ + led = GPIOF -> DATA; + led |= 0x08; + GPIOF -> DATA = led; + Delay(60); + led = GPIOF -> DATA; + led &= 0xF7; + GPIOF -> DATA = led; + } + } +} + +void Delay(int t) +{ + volatile long time; + int i; + for (i = 0; i < t; ++i){ + time = 145000; + while(time) + time--; + } +} \ No newline at end of file diff --git a/Linked List/MyDefines.h b/Linked List/MyDefines.h new file mode 100755 index 0000000..fb99053 --- /dev/null +++ b/Linked List/MyDefines.h @@ -0,0 +1,43 @@ +#ifndef __MYDEFINES_H +#define __MYDEFINES_H + +#define _PIN0 0x01 +#define _PIN1 0x02 +#define _PIN2 0x04 +#define _PIN3 0x08 +#define _PIN4 0x10 +#define _PIN5 0x20 +#define _PIN6 0x40 +#define _PIN7 0x80 + +#define _PORTA 0x0001 +#define _PORTB 0x0002 +#define _PORTC 0x0004 +#define _PORTD 0x0008 +#define _PORTE 0x0010 +#define _PORTF 0x0020 + + +#define _PWM_MODULE0 0x01 +#define _PWM_MODULE1 0x02 + +#define _PWM0 0x01 +#define _PWM1 0x02 +#define _PWM2 0x04 +#define _PWM3 0x08 +#define _PWM4 0x10 +#define _PWM5 0x20 +#define _PWM6 0x40 +#define _PWM7 0x80 + +#define _PWMDIV_2 0x0 +#define _PWMDIV_4 0x1 +#define _PWMDIV_8 0x2 +#define _PWMDIV_16 0x3 +#define _PWMDIV_32 0x4 +#define _PWMDIV_64 0x5 + +#define _PWM_LEFT_ALIG_CMPAD ((0x02 << 6) | (0x03 << 2)) +#define _PWM_LEFT_ALIG_CMPBD ((0x02 << 10) | (0x03 << 2)) + +#endif \ No newline at end of file diff --git a/Linked List/main.c b/Linked List/main.c new file mode 100755 index 0000000..4e45d5c --- /dev/null +++ b/Linked List/main.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include + +#include "MyDefines.h" +#include + +void Delay(int s) +{ + volatile int i, j; + for (i = 0; i < s; i++) + for (j = 0; j < 3180; j++){} +} + +void SetupGPIO(void); + +typedef struct STEPS{ + struct STEPS* prev; + uint8_t pinout1; + uint8_t pinout2; + struct STEPS* next; +} STEPS; + +#define CW 0 +#define CCW 1 +void Stepper(int s, bool direction); + +STEPS step[]={ + {&step[3], _PIN0, _PIN1, &step[1]}, + {&step[2], _PIN1, _PIN2, &step[2]}, + {&step[1], _PIN2, _PIN3, &step[3]}, + {&step[0], _PIN3, _PIN0, &step[0]}, +}; + +int main() +{ + int i = 0; + + SetupGPIO(); + + while(1){ + + for ( i = 0; i < 10; i++){ + Stepper(10, CW); + Delay(10); + } + /* + for (i = 0; i < 10; i++){ + Stepper(10, CCW); + Delay(10); + }*/ + } + +} + +void SetupGPIO(void) +{ + // GPIO Initialization and Configuration + // 1. Enable Clock on GPIOs + SYSCTL->RCGCGPIO |= _PORTD; + // allow time for clock to stabilize + while ((SYSCTL->PRGPIO & _PORTD) != _PORTD) {}; + // 2. Unlock PD7 and/or PF0 for TM4C 123G + // 3. Config AMSEL to disable analog function + // 4. Config PCTL to select 0-GPIO + // 5. Set AFSEL bits to 0 + // 6. Set DIR to 0 for input, 1 for output + GPIOD -> DIR = _PIN0|_PIN1|_PIN2|_PIN3; + // 7. Set PUR/PDR/ODR bits to 1 to enable internal pull-up/-down resistir and/or open-drain + // 8. Set DEN bits to 1 to enable all + GPIOD -> DEN = _PIN0|_PIN1|_PIN2|_PIN3; + +} +void Stepper(int s, bool direction) +{ + int i; + STEPS* p = step; + + for (i = 0; i< s; i++){ + if (direction == CW){ + // p pointed to next element of step array + GPIOD -> DATA |= ((p->pinout1)|(p->pinout2)); + Delay(10); + GPIOD -> DATA &= ~((p->pinout1)|(p->pinout2)); + p = p->next; + } else { + GPIOD -> DATA |= ((p->pinout1)|(p->pinout2)); + Delay(10); + GPIOD -> DATA &= ~((p->pinout1)|(p->pinout2)); + p = p->prev; + + } + // Port = p->pinout; + + } +} + \ No newline at end of file diff --git a/MyDefines.h b/MyDefines.h new file mode 100755 index 0000000..146c609 --- /dev/null +++ b/MyDefines.h @@ -0,0 +1,65 @@ +#ifndef __MYDEFINES_H +#define __MYDEFINES_H + +#define _PIN0 0x01 +#define _PIN1 0x02 +#define _PIN2 0x04 +#define _PIN3 0x08 +#define _PIN4 0x10 +#define _PIN5 0x20 +#define _PIN6 0x40 +#define _PIN7 0x80 + +#define _PORTA 0x0001 +#define _PORTB 0x0002 +#define _PORTC 0x0004 +#define _PORTD 0x0008 +#define _PORTE 0x0010 +#define _PORTF 0x0020 + + +#define _PWM_MODULE0 0x01 +#define _PWM_MODULE1 0x02 + +#define _PWM0 0x01 +#define _PWM1 0x02 +#define _PWM2 0x04 +#define _PWM3 0x08 +#define _PWM4 0x10 +#define _PWM5 0x20 +#define _PWM6 0x40 +#define _PWM7 0x80 + +#define _PWMDIV_2 0x0 +#define _PWMDIV_4 0x1 +#define _PWMDIV_8 0x2 +#define _PWMDIV_16 0x3 +#define _PWMDIV_32 0x4 +#define _PWMDIV_64 0x5 + +#define _PWM_LEFT_ALIG_CMPAD ((0x02 << 6) | (0x03 << 2)) +#define _PWM_LEFT_ALIG_CMPBD ((0x02 << 10) | (0x03 << 2)) + +#define _PWM_RIGHT_ALIG_CMPAD ((0x03 << 6) | (0x02 << 2)) +#define _PWM_RIGHT_ALIG_CMPBD ((0x03 << 10) | (0x02 << 2)) + +#define _TIMER0 0x01 +#define _TIMER1 0x02 +#define _TIMER2 0x04 +#define _TIMER3 0x08 +#define _TIMER4 0x10 +#define _TIMER5 0x20 +#define _TIMER6 0x40 +#define _TIMER7 0x80 + +#define _TIMERA_ENABLE (1 << 0) +#define _TIMERB_ENABLE (1 << 8) +#define _TIMERA_COUNTUP (1 << 4) +#define _TIMERA_COUNTDOWN (0 << 4) +#define _TIMERA_CAPTURE 0x03 +#define _TIMERA_EDGE_TIME (1 << 2) +#define _TIMERA_POSITIVE_EDGE 0 +#define _TIMERA_NEGATIVE_EDGE (1 << 2) +#define _TIMERA_BOTH_EDGES (3 << 2) + +#endif \ No newline at end of file diff --git a/PWM DC Motor/MyDefines.h b/PWM DC Motor/MyDefines.h new file mode 100755 index 0000000..fb99053 --- /dev/null +++ b/PWM DC Motor/MyDefines.h @@ -0,0 +1,43 @@ +#ifndef __MYDEFINES_H +#define __MYDEFINES_H + +#define _PIN0 0x01 +#define _PIN1 0x02 +#define _PIN2 0x04 +#define _PIN3 0x08 +#define _PIN4 0x10 +#define _PIN5 0x20 +#define _PIN6 0x40 +#define _PIN7 0x80 + +#define _PORTA 0x0001 +#define _PORTB 0x0002 +#define _PORTC 0x0004 +#define _PORTD 0x0008 +#define _PORTE 0x0010 +#define _PORTF 0x0020 + + +#define _PWM_MODULE0 0x01 +#define _PWM_MODULE1 0x02 + +#define _PWM0 0x01 +#define _PWM1 0x02 +#define _PWM2 0x04 +#define _PWM3 0x08 +#define _PWM4 0x10 +#define _PWM5 0x20 +#define _PWM6 0x40 +#define _PWM7 0x80 + +#define _PWMDIV_2 0x0 +#define _PWMDIV_4 0x1 +#define _PWMDIV_8 0x2 +#define _PWMDIV_16 0x3 +#define _PWMDIV_32 0x4 +#define _PWMDIV_64 0x5 + +#define _PWM_LEFT_ALIG_CMPAD ((0x02 << 6) | (0x03 << 2)) +#define _PWM_LEFT_ALIG_CMPBD ((0x02 << 10) | (0x03 << 2)) + +#endif \ No newline at end of file diff --git a/PWM DC Motor/MyDevice.h b/PWM DC Motor/MyDevice.h new file mode 100755 index 0000000..e69de29 diff --git a/PWM DC Motor/main.c b/PWM DC Motor/main.c new file mode 100755 index 0000000..01b5016 --- /dev/null +++ b/PWM DC Motor/main.c @@ -0,0 +1,162 @@ +#include +#include +#include +#include +#include "MyDefines.h" + +#include "TM4C123GH6PM.h" + +void SetupPWM(void); +void SetupGPIO(void); +void SetupPWMDEFINE(void); +void SetupGPIODEFINE(void); + +int main() +{ + SetupPWM(); + SetupGPIO(); + + int cmp = 0; + volatile int i; + + while(1){ + // Your Code Here + //GPIOF -> DATA = 0x01; + + PWM1 -> _3_CMPB = cmp; + PWM1 -> _2_CMPA = cmp++; + + if(cmp > 9999) cmp = 0; + + for(i = 0; i < 500; i++){} + } +} + +int mainDEFINE(){ + + uint32_t *sw1 = (uint32_t *)(((char*)GPIOF) + (_PIN4 << 2)); + uint32_t *led = (uint32_t *)(((char*)GPIOF) + (_PIN2 << 2)); + + SetupPWMDEFINE(); + SetupGPIODEFINE(); + + while(1){ + if(!(*sw1)){ + *led = 0xFF; + }else{ + *led = 0x00; + } + } +} + +void SetupGPIODEFINE(void){ + + // Config for GPIO + // 1. Enable Clock on GPIOF + SYSCTL->RCGCGPIO = _PORTF; + // allow time for clock to stabilize + while((SYSCTL->PRGPIO & _PORTF) != _PORTF){}; + + // 2. Unlock GPIO + GPIOF -> LOCK = 0x4C4F434B; + GPIOF -> CR |= 0x01; + // 3. Clear AMSEL to disable analog + GPIOF -> AMSEL = 0x0; + // 4. Config PCTL to select GPIO + GPIOF -> PCTL = 0x5000; + // 5. Set DIR to 0 for input, 1 for output + GPIOF -> DIR = _PIN2 | _PIN3; + // 6. Enable AFSEL bits to 1 + GPIOF -> AFSEL = _PIN3; + // 7. Set PUE bits to 1 to enable internal pull-up + GPIOF -> DATA = _PIN4; + // 8. Set DEN bits to 1 to enable data pins + GPIOF -> DEN = _PIN2 | _PIN3; + +} + +void SetupGPIO(void){ + + // Config for GPIO + // 1. Enable Clock on GPIOF + SYSCTL->RCGCGPIO = 0x20; + // allow time for clock to stabilize + while((SYSCTL->PRGPIO & 0x20) != 0x20){}; + + // 2. Unlock GPIO + GPIOF -> LOCK = 0x4C4F434B; + GPIOF -> CR |= 0x01; + // 3. Clear AMSEL to disable analog + GPIOF -> AMSEL = 0x0; + // 4. Config PCTL to select GPIO + GPIOF -> PCTL = 0x00005005; + // 5. Set DIR to 0 for input, 1 for output + GPIOF -> DIR = 0x09; + // 6. Enable AFSEL bits to 1 + GPIOF -> AFSEL = 0x09; + // 7. Set PUE bits to 1 to enable internal pull-up + // 8. Set DEN bits to 1 to enable data pins + GPIOF -> DEN = 0x09; +} + +void SetupPWMDEFINE(void) +{ + int load = 40000; + // 1. Enable Clock for PWM Module 1 + SYSCTL->RCGCPWM |= _PWM_MODULE1; + while((SYSCTL->PRPWM & _PWM_MODULE1)!= _PWM_MODULE1){}; + // 2. Enable and Setup Clock Divider for PWM + SYSCTL->RCC |= (1 << 20); // RCC[20]=1:USEPWMDIV + SYSCTL->RCC &= ~0x000E0000; // RCC[19:17]=000 PWMDIV + SYSCTL->RCC |= (_PWMDIV_2 << 17); // RCC[19:17]=0x04 divider=/32 + // 3. Disable PWM Generator 2 + PWM1->_2_CTL &= ~0x01; // Disable PWM Generator 2 + PWM1->_3_CTL &= ~0x01; // Disable PWM Generator 3 + // 4. Config LOAD, CMPn, GENn values + + PWM1->_2_LOAD = load; // GEN 2 A PWM 4 PF0 MOTOR + PWM1->_2_CMPA = load/2; + PWM1->_2_GENA = _PWM_LEFT_ALIG_CMPBD;//0x080C + + PWM1->_3_LOAD = load; // GEN 3 B PWM 7 PF3 LED + PWM1->_3_CMPB = load/2; + PWM1->_3_GENB = (0x02 << 10 ) | (0x03 <<2);//0x080C + // 5. Enable PWM Generator 2 + PWM1->_2_CTL |= 0x01; + PWM1->_3_CTL |= 0x01; + // 6. Enable PWM5 Output + //PWM1->ENABLE |= 1 << 4; // Enable PWM4 + //PWM1->ENABLE |= 1 << 7; // Enable PWM7 + PWM1 -> ENABLE |= 0x90; +} + +void SetupPWM(void) +{ + int load = 10000; + // 1. Enable Clock for PWM Module 1 + SYSCTL->RCGCPWM |= 0x02; + while((SYSCTL->PRPWM & 0x02)==0){}; + // 2. Enable and Setup Clock Divider for PWM + SYSCTL->RCC |= (1 << 20); // RCC[20]=1:USEPWMDIV + SYSCTL->RCC &= ~0x000E0000; // RCC[19:17]=000 PWMDIV + SYSCTL->RCC |= (0x03 << 17); // RCC[19:17]=0x04 divider=/32 + // 3. Disable PWM Generator 2 + PWM1->_2_CTL &= ~0x01; // Disable PWM Generator 2 + PWM1->_3_CTL &= ~0x01; // Disable PWM Generator 3 + // 4. Config LOAD, CMPn, GENn values + + PWM1->_2_LOAD = load; // GEN 2 A PWM 4 PF0 MOTOR + PWM1->_2_CMPA = load/2; + PWM1->_2_GENA = (0x02 << 6 ) | (0x03 <<2);//0x080C + + PWM1->_3_LOAD = load; // GEN 3 B PWM 7 PF3 LED + PWM1->_3_CMPB = load/2; + PWM1->_3_GENB = (0x02 << 10 ) | (0x03 <<2);//0x080C + // 5. Enable PWM Generator 2 + PWM1->_2_CTL |= 0x01; + PWM1->_3_CTL |= 0x01; + // 6. Enable PWM5 Output + //PWM1->ENABLE |= 1 << 4; // Enable PWM4 + //PWM1->ENABLE |= 1 << 7; // Enable PWM7 + PWM1 -> ENABLE |= 0x90; +} \ No newline at end of file diff --git a/PinPad/MyDefines.h b/PinPad/MyDefines.h new file mode 100755 index 0000000..7aa5515 --- /dev/null +++ b/PinPad/MyDefines.h @@ -0,0 +1,43 @@ +#ifndef __MYDEFINES_H +#define __MYDEFINES_H + +#define _PIN0 0x01 +#define _PIN1 0x02 +#define _PIN2 0x04 +#define _PIN3 0x08 +#define _PIN4 0x10 +#define _PIN5 0x20 +#define _PIN6 0x40 +#define _PIN7 0x80 + +#define _PORTA 0x01 +#define _PORTB 0x02 +#define _PORTC 0x04 +#define _PORTD 0x08 +#define _PORTE 0x10 +#define _PORTF 0x20 + + +#define _PWM_MODULE0 0x01 +#define _PWM_MODULE1 0x02 + +#define _PWM0 0x01 +#define _PWM1 0x02 +#define _PWM2 0x04 +#define _PWM3 0x08 +#define _PWM4 0x10 +#define _PWM5 0x20 +#define _PWM6 0x40 +#define _PWM7 0x80 + +#define _PWMDIV_2 0x0 +#define _PWMDIV_4 0x1 +#define _PWMDIV_8 0x2 +#define _PWMDIV_16 0x3 +#define _PWMDIV_32 0x4 +#define _PWMDIV_64 0x5 + +#define _PWM_LEFT_ALIG_CMPAD ((0x02 << 6) | (0x03 << 2)) +#define _PWM_LEFT_ALIG_CMPBD ((0x02 << 10) | (0x03 << 2)) + +#endif \ No newline at end of file diff --git a/PinPad/pinpad.c b/PinPad/pinpad.c new file mode 100755 index 0000000..0e586f1 --- /dev/null +++ b/PinPad/pinpad.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include + +#include "TM4C123GH6PM.h" +#include "ez123G.h" +#include "MyDefines.h" + +char str[100]; +char ReadKeyPad(); + +int main(void) +{ + PEZOBJ_LCD lcd; + uint16_t i = 0; + + // GPIO Initialization and Configuration + // 1. Enable Clock on GPIOs + SYSCTL->RCGCGPIO |= 0x1B; + // allow time for clock to stabilize + while ((SYSCTL->PRGPIO & 0x1B) != 0x1B) {}; + // 2. Unlock PD7 and/or PF0 for TM4C 123G + // 3. Config AMSEL to disable analog function + // 4. Config PCTL to select 0-GPIO + // 5. Set AFSEL bits to 0 + // 6. Set DIR to 0 for input, 1 for output + + GPIOA -> DIR = 0x00; + GPIOB -> DIR = 0x03; + GPIOD -> DIR = 0x0F; + GPIOE -> DIR = 0x3E; + + // 7. Set PUR/PDR/ODR bits to 1 to enable internal pull-up/-down resistir and/or open-drain + GPIOB -> ODR = 0x03; + GPIOE -> ODR = 0x30; + GPIOA -> PUR = 0xE0; + GPIOB -> PUR = 0x10; + + // 8. Set DEN bits to 1 to enable all + GPIOA -> DEN = 0xE0; + GPIOB -> DEN = 0x13; + GPIOD -> DEN = 0x0F; + GPIOE -> DEN = 0x3E; + + + lcd = ezLCD_Create(); + ezLCD_Connect_DataPort(lcd, GPIOD, PIN_3_0); + ezLCD_Connect_ENPin(lcd, GPIOE, PIN1); + ezLCD_Connect_RSPin(lcd, GPIOE, PIN2); + ezLCD_Connect_RWPin(lcd, GPIOE, PIN3); + + ezLCD_Start(lcd); + ezLCD_ClearDisplay(lcd); + ezLCD_Position(lcd, 1, 0); + ezLCD_PrintString(lcd, "HELLO"); + + char ch; + while(1){ + ch = ReadKeyPad(); + + if (ch == '*'){ + i *= 100; + ezLCD_ClearDisplay(lcd); + } + if (ch == '#') i = 0; + if (ch >='0' && ch <= '9') i = i*10 + ch - '0'; + + sprintf(str, "%d ", i); + ezLCD_Position(lcd, 0, 0); + ezLCD_PrintString(lcd, str); + + timer_waitMillis(100); + } +} +//-------------------------------------------------------------- +char KeyPad[4][4]={ + {'1','2','3','A'}, + {'4','5','6','B'}, + {'7','8','9','C'}, + {'*','0','#','D'}}; + +char ReadKeyPad() +{ + int row; + GPIOB -> DATA |= 0x03; + GPIOE -> DATA |= 0x30; + for(row = 0; row < 4; row++){ + switch(row){ + case 0: + GPIOB -> DATA &= ~0x01; + break; + case 1: + GPIOB -> DATA |= 0x01; + GPIOB -> DATA &= ~0x02; + break; + case 2: + GPIOB -> DATA |= 0x02; + GPIOE -> DATA &= ~0x10; + break; + case 3: + GPIOE -> DATA |= 0x10; + GPIOE -> DATA &= ~0x20; + break; + } + + timer_waitMillis(10); + + if(!(GPIOB -> DATA & 0x10)) + { + while(!(GPIOB -> DATA & 0x10)){} + return KeyPad[row][0]; + } + if(!(GPIOA -> DATA & 0x20)) + { + while(!(GPIOA -> DATA & 0x20)){} + return KeyPad[row][1]; + } + if(!(GPIOA -> DATA & 0x40)) + { + while(!(GPIOA -> DATA & 0x40)){} + return KeyPad[row][2]; + } + if(!(GPIOA -> DATA & 0x80)) + { + while(!(GPIOA -> DATA & 0x80)){} + return KeyPad[row][3]; + } + + row++; + } + + return 0x0; +} \ No newline at end of file diff --git a/Report Motor Speed/MyDefines.h b/Report Motor Speed/MyDefines.h new file mode 100755 index 0000000..fb99053 --- /dev/null +++ b/Report Motor Speed/MyDefines.h @@ -0,0 +1,43 @@ +#ifndef __MYDEFINES_H +#define __MYDEFINES_H + +#define _PIN0 0x01 +#define _PIN1 0x02 +#define _PIN2 0x04 +#define _PIN3 0x08 +#define _PIN4 0x10 +#define _PIN5 0x20 +#define _PIN6 0x40 +#define _PIN7 0x80 + +#define _PORTA 0x0001 +#define _PORTB 0x0002 +#define _PORTC 0x0004 +#define _PORTD 0x0008 +#define _PORTE 0x0010 +#define _PORTF 0x0020 + + +#define _PWM_MODULE0 0x01 +#define _PWM_MODULE1 0x02 + +#define _PWM0 0x01 +#define _PWM1 0x02 +#define _PWM2 0x04 +#define _PWM3 0x08 +#define _PWM4 0x10 +#define _PWM5 0x20 +#define _PWM6 0x40 +#define _PWM7 0x80 + +#define _PWMDIV_2 0x0 +#define _PWMDIV_4 0x1 +#define _PWMDIV_8 0x2 +#define _PWMDIV_16 0x3 +#define _PWMDIV_32 0x4 +#define _PWMDIV_64 0x5 + +#define _PWM_LEFT_ALIG_CMPAD ((0x02 << 6) | (0x03 << 2)) +#define _PWM_LEFT_ALIG_CMPBD ((0x02 << 10) | (0x03 << 2)) + +#endif \ No newline at end of file diff --git a/Report Motor Speed/main.c b/Report Motor Speed/main.c new file mode 100755 index 0000000..fadfed4 --- /dev/null +++ b/Report Motor Speed/main.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include "MyDefines.h" + +#include "TM4C123GH6PM.h" + +void SetupPWM(void); +void SetupGPIO(void); +void Delay(int t); + +int main() +{ + SetupPWM(); + SetupGPIO(); + + uint32_t *sw1 = (uint32_t *)(((char*)GPIOF) + (_PIN4 << 2)); + uint32_t *sw2 = (uint32_t *)(((char*)GPIOF) + (_PIN0 << 2)); + + uint32_t *cwturn = (uint32_t *)(((char*)GPIOA) + (_PIN3 << 2)); + uint32_t *acwturn = (uint32_t *)(((char*)GPIOA) + (_PIN2 << 2)); + *cwturn = 0xFF; + *acwturn = 0x00; + + bool countup = true; + bool turn_clockwise = true; + + *cwturn = 0xFF; + *acwturn = 0x00; + PWM0 -> ENABLE |= _PWM3; + PWM1 -> ENABLE |= _PWM7; + double cmp_percent = 0.9; //Start at 10% Duty Cycle + + bool sw1currstate; + bool sw1prevstate = false; + + bool sw2currstate; + bool sw2prevstate = false; + + while(1){ + + if(!(*sw1)) sw1currstate = true; + else sw1currstate = false; + if(!(*sw2)) sw2currstate = true; + else sw2currstate = false; + + //DUTY CYCLE CHANGE + if(!sw1currstate && sw1prevstate){ //Falling Edge Triggered + if(cmp_percent == 1){ //count down at 100% duty cycle + countup = false; + } + if(cmp_percent == 0){ //count up at 0% duty cycle + countup = true; + } + if(countup == true){ //add 10% duty cycle + cmp_percent -= 0.1; + }else{ //remove 10% duty cycle + cmp_percent += 0.1; + } + PWM1->_3_CMPB = 20000 - 20000*cmp_percent; + PWM0->_1_CMPB = 20000 - 20000*cmp_percent; + } + + //MOTOR DIRECTION CHANGE + if(!sw2currstate && sw2prevstate){ //Falling Edge Triggered + + PWM0->_1_CMPB = 20000; //Set Duty Cycle 0% + PWM1->_3_CMPB = 20000; + + Delay(2000); //Wait 2 Seconds + + if(turn_clockwise){ + *cwturn = 0x00; + *acwturn = 0xFF; + turn_clockwise = false; + }else{ + *cwturn = 0xFF; + *acwturn = 0x00; + turn_clockwise = true; + } + PWM1->_3_CMPB = 20000*cmp_percent; + PWM0->_1_CMPB = 20000*cmp_percent; + } + sw1prevstate = sw1currstate; + sw2prevstate = sw2currstate; + } +} + + +void SetupGPIO(void){ + + // Config for GPIO + // 1. Enable Clock on GPIOF + SYSCTL->RCGCGPIO = (_PORTA|_PORTB|_PORTF); + // allow time for clock to stabilize + while((SYSCTL->PRGPIO & (_PORTA|_PORTB|_PORTF)) != (_PORTA|_PORTB|_PORTF)){}; + + // 2. Unlock GPIO + GPIOF -> LOCK = 0x4C4F434B; + GPIOF -> CR |= _PIN0; + // 3. Clear AMSEL to disable analog + //GPIOA -> AMSEL = 0x0; + //GPIOB -> AMSEL = 0x0; + //GPIOF -> AMSEL = 0x0; + // 4. Config PCTL to select GPIO + GPIOA -> PCTL = 0x0; + GPIOB -> PCTL = 0x00400000; + GPIOF -> PCTL = 0x00005000; + // 5. Set DIR to 0 for input, 1 for output + GPIOA -> DIR |= _PIN2|_PIN3; + GPIOB -> DIR |= _PIN5; + GPIOF -> DIR |= _PIN3; + // 6. Enable AFSEL bits to 1 + GPIOA -> AFSEL = 0x0; + GPIOB -> AFSEL = _PIN5; + GPIOF -> AFSEL = _PIN3; + // 7. Set PUE bits to 1 to enable internal pull-up + GPIOF -> PUR = _PIN0|_PIN4; + // 8. Set DEN bits to 1 to enable data pins + GPIOA -> DEN |= _PIN2|_PIN3; + GPIOB -> DEN |= _PIN5; + GPIOF -> DEN |= _PIN0|_PIN3|_PIN4; +} + + + +void SetupPWM(void) +{ + int load = 20000; + // 1. Enable Clock for PWM Module 1 + SYSCTL->RCGCPWM |= (_PWM_MODULE0|_PWM_MODULE1); + while((SYSCTL->PRPWM & (_PWM_MODULE0|_PWM_MODULE1))==0){}; + + // 2. Enable and Setup Clock Divider for PWM + SYSCTL->RCC |= (1 << 20); // RCC[20]=1:USEPWMDIV + SYSCTL->RCC &= ~0x000E0000; // RCC[19:17]=000 PWMDIV + SYSCTL->RCC |= (_PWMDIV_4 << 17); // RCC[19:17]=0x04 divider=/32 + + // 3. Disable PWM Generator 2 + PWM0->_1_CTL &= ~0x01; // Disable PWM Generator 2 + PWM1->_3_CTL &= ~0x01; // Disable PWM Generator 2 + + // 4. Config LOAD, CMPn, GENn values + PWM0->_1_LOAD = load; // M0 GEN 1 B PWM 3 PB5 MOTOR + PWM0->_1_CMPB = (load - load*0.1); + PWM0->_1_GENB = (0x02 << 10 ) | (0x03 <<2);//0x080C + + PWM1->_3_LOAD = load; // M1 GEN 3 B PWM 7 PF3 LED + PWM1->_3_CMPB = (load - load*0.1); + PWM1->_3_GENB = (0x02 << 10 ) | (0x03 <<2);//0x080C + + // 5. Enable PWM Generator 2 + PWM0->_1_CTL |= 0x01; + PWM1->_3_CTL |= 0x01; + + // 6. Enable PWM5 Output + +} + +void Delay(int t) +{ + volatile int i, j; + for (i = 0; i < t; i++) + for (j = 0; j < 3180; j++) + {}; +} \ No newline at end of file diff --git a/State Machine/MyDefines.h b/State Machine/MyDefines.h new file mode 100755 index 0000000..fb99053 --- /dev/null +++ b/State Machine/MyDefines.h @@ -0,0 +1,43 @@ +#ifndef __MYDEFINES_H +#define __MYDEFINES_H + +#define _PIN0 0x01 +#define _PIN1 0x02 +#define _PIN2 0x04 +#define _PIN3 0x08 +#define _PIN4 0x10 +#define _PIN5 0x20 +#define _PIN6 0x40 +#define _PIN7 0x80 + +#define _PORTA 0x0001 +#define _PORTB 0x0002 +#define _PORTC 0x0004 +#define _PORTD 0x0008 +#define _PORTE 0x0010 +#define _PORTF 0x0020 + + +#define _PWM_MODULE0 0x01 +#define _PWM_MODULE1 0x02 + +#define _PWM0 0x01 +#define _PWM1 0x02 +#define _PWM2 0x04 +#define _PWM3 0x08 +#define _PWM4 0x10 +#define _PWM5 0x20 +#define _PWM6 0x40 +#define _PWM7 0x80 + +#define _PWMDIV_2 0x0 +#define _PWMDIV_4 0x1 +#define _PWMDIV_8 0x2 +#define _PWMDIV_16 0x3 +#define _PWMDIV_32 0x4 +#define _PWMDIV_64 0x5 + +#define _PWM_LEFT_ALIG_CMPAD ((0x02 << 6) | (0x03 << 2)) +#define _PWM_LEFT_ALIG_CMPBD ((0x02 << 10) | (0x03 << 2)) + +#endif \ No newline at end of file diff --git a/State Machine/main.c b/State Machine/main.c new file mode 100755 index 0000000..ea29fd8 --- /dev/null +++ b/State Machine/main.c @@ -0,0 +1,188 @@ +#include "MyDefines.h" +#include +#include +#include +#include + +#include "TM4C123GH6PM.h" + + typedef enum STATES { + S_0, + S_1, + S_2, + S_3, +}STATES; + +void SetGPIO(void); +void GPIOF_Handler (void); +void Setup_GPIOIRQ(void); + +volatile bool sw1; + + uint32_t *led1 =(uint32_t *) (((char*)GPIOF) +(_PIN1 << 2)); + uint32_t *led2 =(uint32_t *) (((char*)GPIOF) +(_PIN3 << 2)); + +typedef struct STATELIST{ + int led1; + int led2; + struct STATELIST *next; + +}STATELIST; + +int main() +{ + STATES currState = S_0; + + STATELIST state[] = { + {0, 0, &state[1]}, //s0 + {0xFF, 0, &state[2]}, //s1 + {0xFF, 0xFF, &state[3]}, //s2 + {0, 0xFF, &state[0]}, //s3 + }; + + SetGPIO(); + Setup_GPIOIRQ (); + +//Moore State Machine +while(1){ + switch (currState){ + case S_0: + *led1 = 0x00; + *led2 = 0x00; + if(sw1){ + sw1=false; + currState = S_1; + } + break; + case S_1: + *led1 = 0x01; + *led2 = 0x00; + if(sw1){ + sw1=false; + currState = S_2; + } + break; + case S_2: + *led1 = 0x01; + *led2 = 0x01; + if(sw1){ + sw1=false; + currState = S_3; + } + break; + case S_3: + *led1 = 0x00; + *led2 = 0x01; + if(sw1){ + sw1=false; + currState = S_0; + } + break; + + } + } + +//Mealy State Machine +while(1){ + switch (currState){ + case S_0: + if(sw1){ + sw1=false; + currState = S_1; + *led1 = 0x00; + *led2 = 0x00; + } + break; + case S_1: + if(sw1){ + sw1=false; + currState = S_2; + *led1 = 0x01; + *led2 = 0x00; + } + break; + case S_2: + if(sw1){ + sw1=false; + currState = S_3; + *led1 = 0x01; + *led2 = 0x01; + } + break; + case S_3: + if(sw1){ + sw1=false; + currState = S_0; + *led1 = 0x00; + *led2 = 0x01; + } + break; + + } + } + +//MOORE STATE WITH LINKED LIST +STATELIST *pState = &state[0]; +while(1){ + *led1 = pState->led1; + *led2 = pState->led2; + if(sw1){ + + } +} +} +void SetGPIO(void) +{ + // Config for GPIO + // 1. Enable Clock on GPIOF + SYSCTL->RCGCGPIO = _PORTF; + // allow time for clock to stabilize + while((SYSCTL->PRGPIO & _PORTF) != _PORTF){}; + + // 2. Unlock GPIO + + // 3. Clear AMSEL to disable analog + // 4. Config PCTL to select GPIO + GPIOF->PCTL= 0x00; + // 5. Set DIR to 0 for input, 1 for output + GPIOF->DIR= _PIN1 | _PIN2; + // 6. Enable AFSEL bits to 1 + + // 7. Set PUE bits to 1 to enable internal pull-up + GPIOF->PUR= _PIN4; + // 8. Set DEN bits to 1 to enable data pins + GPIOF->DEN= _PIN1 | _PIN4 | _PIN2; +} + +void Setup_GPIOIRQ() +{ + uint16_t n,m,r,r2; + // 1. Disable IRQ in GPIOIM register + GPIOF->IM &= ~(_PIN4); + // 2. Configure IRQ Type (0=edge, 1=level) in the GPIOIS register + GPIOF->IS &= ~(_PIN4); + // 3. Configure GPIOIBE (0=single edge, 1=both edge), + // GPIOIEV (0=low level or falling edge, 1=high level or rising edge) + GPIOF->IBE &= ~(_PIN4); + GPIOF->IEV &= ~(_PIN4); + // 4. Clear the GPIORIS register + GPIOF->ICR |= _PIN4; + // 5. Enable IRQ in the GPIOIM register + GPIOF->IM |= _PIN4; + // 6. Set priority in the NVIC + n = 30/4; + r = 21; + m = 30/32; r2 = 30 % 32; + NVIC->IP[n] |= (3 << r); + // 7. Enable IRQ in the NVIC + NVIC->ISER[m] |= (1 << r2); +} + uint32_t *pn1 =(uint32_t *) (((char*)GPIOF) +(_PIN4 << 2)); + +void GPIOF_Handler()//Interrupt service +{ + GPIOF ->ICR |= _PIN4; // Clear Interrupt flag + sw1=true; + //*pn1 ^= _PIN1; + +} \ No newline at end of file diff --git a/TemplateCode_01.c b/TemplateCode_01.c new file mode 100755 index 0000000..744c0d6 --- /dev/null +++ b/TemplateCode_01.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "TM4C123GH6PM.h" +#include "MyDefines.h" +#include "ez123G.h" +void initGPIO(void); +void initTimer(void); + +uint32_t deltaT; + +void UltraSonic(); +uint32_t MeasureD(); + +int main(void) +{ + Setup_123G_80MHz(); //Setup System Clock to 80MHz + initTimer(); + initGPIO(); + + for(;;){ + + } +} + +// trig->pf3 for 123G +uint32_t *pf3; +void UltraSonic(){ + uint32_t pulseWidth; + //Set "Trig" pin to low for 500ms + *pf3 = 00; + timer_waitMillis(500); //Waiting for 500 ms + //Set "trig" pin to high for 10 us + *pf3 = _PIN3; //*pf3 = 0xFF + timer_waitMicros(10); + //Call MeasureD() + pulseWidth = MeasureD(); + //Calculate deltaT + + //Calculate distance in cm +} + +uint32_t MeasureD(){ + uint32_t highEdge, lowEdge; + uint32_t pulseCounter; + + //Capture first edge -- rising edge + + //Clear TimerA Capture mode event by clearing bit on ICR register + TIMER1->ICR |= (1 << 2); //CAECINT + //Waiting for capture signal by check RIS register + while ((TIMER1->RIS & (1<<2)) != (1<<2)){} + //read the high Edge from the TAR register + highEdge = (TIMER1->TAR) | (TIMER1->TAPS << 16); + + //capture second edge -- falling edge + //Clear TimerA Capture mode event by clearing bit on ICR register + TIMER1->ICR |= (1 << 2); //CAECINT + //Waiting for capture signal by check RIS register + while ((TIMER1->RIS & (1<<2)) != (1<<2)){} + //read the lowEdge from the TAR register + lowEdge = (TIMER1->TAR) | (TIMER1->TAPS << 16); + if(highEdge > lowEdge) + deltaT = highEdge - lowEdge; + else + deltaT = highEdge + (0xFFFFFF)- lowEdge; + + return pulseCounter; +} + +void initTimer(void){ + //Enable Clock On Timer Module + SYSCTL->RCGCTIMER |= _TIMER1; + while((SYSCTL->PRTIMER & (_TIMER1)) != (_TIMER1)){} + //Disable Timer A/B + TIMER1->CTL &= ~_TIMERA_ENABLE; + //Configure Timer + TIMER1->CFG = 0x04; //Split into two 16-bit timer + //Configure Timer A Mode + TIMER1->TAMR = _TIMERA_COUNTDOWN | _TIMERA_CAPTURE | _TIMERA_EDGE_TIME; + //Configure Timer Event Mode + TIMER1->CTL &= ~(0x03 << 2); + TIMER1->CTL |= _TIMERA_BOTH_EDGES; + //Config Load + TIMER1->TAILR = 0xffff; + //Set the prescaler to 15 + TIMER1->TAPR = 0xff; + TIMER1->IMR = 0; // IMR = interrupt mask = 0, disabled all timer IRQ + //Enable TImer A + TIMER1->CTL |= _TIMERA_ENABLE; +} +void initGPIO(void){ + + // GPIO Configuration + // 1. Enable Clock on GPIOF[3:1] (SYSCTL_RCGCGPIO) + SYSCTL->RCGCGPIO = 0x20; + // allow time for clock to stabilize (SYSCTL_PRGPIO) + while((SYSCTL->PRGPIO & 0x20) != 0x20){}; + // 2. Unlock GPIOC[3:0], GIOD[7] and GPIOF[0] on TM4C123G (GPIOn->LOCK and GPIOn->CR) NOT USING + GPIOF->LOCK = 0x4C4F434B; + GPIOF->CR |= 0x01; + // 3. Clear AMSEL to disable analog + GPIOF->AMSEL = 0x00; + // 4. Config PCTL to select GPIO + GPIOF->PCTL = 0x0000; + //or + //GPIOF->PCTL &= 0xFFF00FFF; + // 5. Set DIR to 0 for input, 1 for output + GPIOF->DIR = 0x0E; // PF3,PF2,PF1 for Output + // 6. Enable AFSEL bits to 1 + GPIOF->AFSEL = 0x00; + // 7. Set PUR bits to 1 to enable internal pull-up + GPIOF->PUR = 0x11; + // 8. Set DEN bits to 1 to enable data pins + GPIOF->DEN = 0x1F; // Enable digital pin on PF3,PF2,PF1 +} diff --git a/Ultrasonic/MyDefines.h b/Ultrasonic/MyDefines.h new file mode 100755 index 0000000..3e69e6f --- /dev/null +++ b/Ultrasonic/MyDefines.h @@ -0,0 +1,62 @@ +#ifndef __MYDEFINES_H +#define __MYDEFINES_H + +#define _PIN0 0x01 +#define _PIN1 0x02 +#define _PIN2 0x04 +#define _PIN3 0x08 +#define _PIN4 0x10 +#define _PIN5 0x20 +#define _PIN6 0x40 +#define _PIN7 0x80 + +#define _PORTA 0x0001 +#define _PORTB 0x0002 +#define _PORTC 0x0004 +#define _PORTD 0x0008 +#define _PORTE 0x0010 +#define _PORTF 0x0020 + + +#define _PWM_MODULE0 0x01 +#define _PWM_MODULE1 0x02 + +#define _PWM0 0x01 +#define _PWM1 0x02 +#define _PWM2 0x04 +#define _PWM3 0x08 +#define _PWM4 0x10 +#define _PWM5 0x20 +#define _PWM6 0x40 +#define _PWM7 0x80 + +#define _PWMDIV_2 0x0 +#define _PWMDIV_4 0x1 +#define _PWMDIV_8 0x2 +#define _PWMDIV_16 0x3 +#define _PWMDIV_32 0x4 +#define _PWMDIV_64 0x5 + +#define _PWM_LEFT_ALIG_CMPAD ((0x02 << 6) | (0x03 << 2)) +#define _PWM_LEFT_ALIG_CMPBD ((0x02 << 10) | (0x03 << 2)) + +#define _TIMER0 0x01 +#define _TIMER1 0x02 +#define _TIMER2 0x04 +#define _TIMER3 0x08 +#define _TIMER4 0x10 +#define _TIMER5 0x20 +#define _TIMER6 0x40 +#define _TIMER7 0x80 + +#define _TIMERA_ENABLE (1 << 0) +#define _TIMERB_ENABLE (1 << 8) +#define _TIMERA_COUNTUP (1 << 4) +#define _TIMERA_COUNTDOWN (0 << 4) +#define _TIMERA_CAPTURE 0x03 +#define _TIMERA_EDGE_TIME (1 << 2) +#define _TIMERA_POSITIVE_EDGE 0 +#define _TIMERA_NEGATIVE_EDGE (1 << 2) +#define _TIMERA_BOTH_EDGES (3 << 2) + +#endif \ No newline at end of file diff --git a/Ultrasonic/main.c b/Ultrasonic/main.c new file mode 100755 index 0000000..c28fc3f --- /dev/null +++ b/Ultrasonic/main.c @@ -0,0 +1,165 @@ +#include +#include +#include +#include + +#include "TM4C123GH6PM.h" +#include "ez123G.h" +#include "MyDefines.h" + +char str[100]; + +void Setup_GPIO(void); +uint32_t getWidth(); +uint32_t measureD(void); +void Setup_Timer(void); + +int main(void) +{ + uint16_t i = 0; + + Setup_123G_80MHz(); + Setup_Timer(); + Setup_GPIO(); + + PEZOBJ_LCD lcd; + lcd = ezLCD_Create(); + ezLCD_Connect_DataPort(lcd, GPIOD, PIN_3_0); + ezLCD_Connect_ENPin(lcd, GPIOE, PIN1); + ezLCD_Connect_RSPin(lcd, GPIOE, PIN2); + ezLCD_Connect_RWPin(lcd, GPIOE, PIN3); + + double time; + double distance; + uint32_t widthArray[3]; + uint32_t avgWidth; + ezLCD_Start(lcd); + ezLCD_LoadVerticalBargraphFonts(lcd); + while(1){ + + widthArray[0] = getWidth(); + //widthArray[1] = getWidth(); + //widthArray[2] = getWidth(); + //avgWidth = (widthArray[0]+widthArray[1]+widthArray[2])/3; + time = widthArray[0] * (1.25E-8); + distance = time * (34000/2); + + ezLCD_Position(lcd, 0, 0); + sprintf(str,"%d: width: %2d", ++i, widthArray[0]); + ezLCD_PrintString(lcd, str); + ezLCD_Position(lcd, 1, 0); + sprintf(str,"dist(cm): %6.2lf cm \n\r", distance); + ezLCD_PrintString(lcd, str); + //timer_waitMillis(100); + } + +} + +uint32_t getWidth() +{ + uint32_t pulseWidth = 0; + uint32_t *trig = (uint32_t *)(((char*)GPIOF) + (_PIN3 << 2)); + // Set "Trig" pin to Low + *trig = 0x00; + timer_waitMillis(500); // Waiting for 500ms + // Set "Trig" pin to High for 10ns + *trig = 0xFF; + timer_waitMicros(10); // Waiting for 10ns + // Set "Trig" pin to Low + *trig = 0x00; + pulseWidth = measureD(); // Call measureD() to get the delta t on the "echo" pin + // Calculate distance + + return pulseWidth; +} + +uint32_t measureD(void) +{ + uint32_t highEdge,lowEdge; + uint32_t deltaT; + + /*Capture firstEgde i.e. rising edge*/ + //1. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register + TIMER1 -> ICR = 1 << 2; + //2. Waiting for capture rising edge event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while((TIMER1 -> RIS & (1 << 2)) != (1 << 2)){} + //3. Read the highEdge from GPTMTAR (TIMER1->TAR) registers + highEdge = TIMER1 -> TAR; + /*Capture secondEgde i.e. falling edge*/ + //4. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register + TIMER1 -> ICR = 1 << 2; + //5. Waiting for capture falling edge event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while((TIMER1 -> RIS & (1 << 2)) != (1 << 2)){} + //6. Read the lowEdge from GPTMTAR (TIMERa->TAR) registers + lowEdge = TIMER1 -> TAR; + //7. Calculate deltaT = highEdge - lowEdge + // Note: the deltaT must large than zero, cannot be negative value + if(highEdge > lowEdge){ + deltaT = highEdge - lowEdge; + }else{ + deltaT = 0xFFFFFFFF - (lowEdge - highEdge); + } + return deltaT; +} + +void Setup_Timer(void) +{ + //* PF2: T1CCP0 (PCTL=07) both edge (edge-time mode) + + // 1 . Enable Clock for TIMER Module + SYSCTL->RCGCTIMER |= (_TIMER1); + while ((SYSCTL->PRTIMER & (_TIMER1)) != (_TIMER1)) {} + // 2. Disable TIMER + TIMER1->CTL &= ~(_TIMERA_ENABLE); // Disable TimerA & TimerB + // 3. Configure TIMER + TIMER1->CFG = 0x04; // Split into two 16-bit timers + // 4. Configure Timer n Mode: GPTMTAMR + TIMER1->TAMR = (_TIMERA_COUNTDOWN|_TIMERA_EDGE_TIME|_TIMERA_CAPTURE); + // 5. Configure Timer Event Mode: rising-, falling-, or both-edges + TIMER1->CTL &= ~(0x03 << 2); + TIMER1->CTL |= (_TIMERA_BOTH_EDGES); // Both edges + // 6. Configure Load + TIMER1->TAILR = 0xFFFF; + //Set the prescaler to 0xFF + TIMER1->TAPR = 0xFF; + TIMER1->IMR = 0; + // 7. Enable GPTM Timer + TIMER1->CTL |= _TIMERA_ENABLE; // Enable TimerB +} + +void Setup_GPIO(void) +{ + + // GPIO Initialization and Configuration + // 1. Enable Clock to the GPIO Modules (SYSCTL->RCGCGPIO) + SYSCTL->RCGCGPIO |= _PORTD|_PORTE|_PORTF; + // allow time for clock to stabilize (SYSCTL->PRGPIO) + while((SYSCTL->PRGPIO & (_PORTD|_PORTE|_PORTF)) != (_PORTD|_PORTE|_PORTF)){}; + // 2. Unlock PD7 and PF0 on TM4C123G; or PD7 on TM4C1294 (GPIO->LOCK and GPIO->CR) + // 3. GPIO Analog Mode Select (GPIOAMSEL) + GPIOD -> AMSEL = 0x0; + GPIOE -> AMSEL = 0x0; + GPIOF -> AMSEL = 0x0; + // 4. GPIO Port COntrol (GPIOPCTL) + GPIOD -> PCTL = 0x0; + GPIOE -> PCTL = 0x0; + GPIOF -> PCTL = 0x00000700; + // 5. Clear AFSEL bits to 0 to select regular I/O + GPIOD -> AFSEL = 0x0; + GPIOE -> AFSEL = 0x0; + GPIOF -> AFSEL |= _PIN2; + // 6. GPIO Pin Direction (GPIODIR) 0 for input, 1 for output + GPIOD -> DIR |= _PIN0|_PIN1|_PIN2|_PIN3; + GPIOE -> DIR |= _PIN1|_PIN2|_PIN3; + GPIOF -> DIR |= _PIN3; + // 7. Set PUR bits to 1 to enable internal pull-up resistor + // 8. Set DEN bits to 1 to enable data pins + GPIOD -> DEN |= _PIN0|_PIN1|_PIN2|_PIN3; + GPIOE -> DEN |= _PIN1|_PIN2|_PIN3; + GPIOF -> DEN |= _PIN2|_PIN3; + +} \ No newline at end of file diff --git a/addserieslcd.txt b/addserieslcd.txt new file mode 100755 index 0000000..a84d920 --- /dev/null +++ b/addserieslcd.txt @@ -0,0 +1,68 @@ +#include +#include +#include +#include + +#include "TM4C123GH6PM.h" +#include "ez123G.h" + +char str[100]; + +int main(void) +{ + PEZOBJ_LCD lcd; + uint16_t i = 0; + + // Enable GPIOD[3:0] and GPIOE[3:1] + // Config for GPIOD and GPIOE + // 1. Enable Clock on GPIOs + SYSCTL->RCGCGPIO |= 0x18; + // allow time for clock to stabilize + while ((SYSCTL->PRGPIO & 0x18) != 0x18) {}; + // 2. Unlock PD7 + GPIOD->LOCK = 0x4C4F434B; + GPIOD->CR |= 0x80; + + // 3. Config AMSEL to disable analog function + GPIOD -> AMSEL = 0x00; + GPIOE -> AMSEL = 0x00; + // 4. Config PCTL to select GPIO + GPIOD -> PCTL = 0x00; + GPIOE -> PCTL = 0x00; + // 5. Set DIR to 0 for input, 1 for output + GPIOD -> DIR |= 0x0F; + GPIOE -> DIR |= 0x0E; + + // 6. Set AFSEL bits to 0 + GPIOD -> AFSEL = 0x00; + GPIOE -> AFSEL = 0x00; + // 7. Set PUE bits to 1 to enable internal pull-up (Skipped) + // 8. Set DEN bits to 1 to enable data pins + GPIOD -> DEN |= 0x0F; + GPIOE -> DEN |= 0x0E; + + + lcd = ezLCD_Create(); + ezLCD_Connect_DataPort(lcd, GPIOD, PIN_3_0); + ezLCD_Connect_ENPin(lcd, GPIOE, PIN1); + ezLCD_Connect_RSPin(lcd, GPIOE, PIN2); + ezLCD_Connect_RWPin(lcd, GPIOE, PIN3); + + ezLCD_Start(lcd); + ezLCD_LoadVerticalBargraphFonts(lcd); + + ezLCD_ClearDisplay(lcd); + int a = 4; + int total = 0; + while(a <= 120){ + ezLCD_Position(lcd, 0, 0); + sprintf(str, "+ %d", a); + total += a; + ezLCD_PrintString(lcd, str); + ezLCD_Position(lcd, 1, 0); + sprintf(str, "=%d", total); + ezLCD_PrintString(lcd, str); + a += 2; + timer_waitMillis(50); + } +} \ No newline at end of file diff --git a/average.txt b/average.txt new file mode 100755 index 0000000..4741780 --- /dev/null +++ b/average.txt @@ -0,0 +1,81 @@ +#include +#include +#include +#include + +#include "TM4C123GH6PM.h" +#include "ez123G.h" + +char str[100]; + +int main(void) +{ + PEZOBJ_LCD lcd; + uint16_t i = 0; + int array[]= {10, 35, 65, 43, 32, 86, 44, 9, 18}; + + // Enable GPIOD[3:0] and GPIOE[3:1] + // Config for GPIOD and GPIOE + // 1. Enable Clock on GPIOs + SYSCTL->RCGCGPIO |= 0x18; + // allow time for clock to stabilize + while ((SYSCTL->PRGPIO & 0x18) != 0x18) {}; + // 2. Unlock PD7 + GPIOD->LOCK = 0x4C4F434B; + GPIOD->CR |= 0x80; + + // 3. Config AMSEL to disable analog function + GPIOD -> AMSEL = 0x00; + GPIOE -> AMSEL = 0x00; + // 4. Config PCTL to select GPIO + GPIOD -> PCTL = 0x00; + GPIOE -> PCTL = 0x00; + // 5. Set DIR to 0 for input, 1 for output + GPIOD -> DIR |= 0x0F; + GPIOE -> DIR |= 0x0E; + + // 6. Set AFSEL bits to 0 + GPIOD -> AFSEL = 0x00; + GPIOE -> AFSEL = 0x00; + // 7. Set PUE bits to 1 to enable internal pull-up (Skipped) + // 8. Set DEN bits to 1 to enable data pins + GPIOD -> DEN |= 0x0F; + GPIOE -> DEN |= 0x0E; + + + lcd = ezLCD_Create(); + ezLCD_Connect_DataPort(lcd, GPIOD, PIN_3_0); + ezLCD_Connect_ENPin(lcd, GPIOE, PIN1); + ezLCD_Connect_RSPin(lcd, GPIOE, PIN2); + ezLCD_Connect_RWPin(lcd, GPIOE, PIN3); + + ezLCD_Start(lcd); + ezLCD_LoadVerticalBargraphFonts(lcd); + + ezLCD_ClearDisplay(lcd); + + int j = 0; + int a = 0, s = 0, M = array[0], m = array[0]; + int total = 0; + while(j <= 8){ + ezLCD_ClearDisplay(lcd); + s += array[j]; + if(array[j] > M) M = array[j]; + if(array[j] < m) m = array[j]; + a = s / (j + 1); + ezLCD_Position(lcd, 0, 0); + sprintf(str, "S=%d", s); + ezLCD_PrintString(lcd, str); + ezLCD_Position(lcd, 0, 8); + sprintf(str, "M=%d", M); + ezLCD_PrintString(lcd, str); + ezLCD_Position(lcd, 1, 0); + sprintf(str, "A=%d", a); + ezLCD_PrintString(lcd, str); + ezLCD_Position(lcd, 1, 8); + sprintf(str, "m=%d", m); + ezLCD_PrintString(lcd, str); + timer_waitMillis(500); + j++; + } +} \ No newline at end of file diff --git a/ezTivaLib/Defines.h b/ezTivaLib/Defines.h new file mode 100755 index 0000000..18ae81e --- /dev/null +++ b/ezTivaLib/Defines.h @@ -0,0 +1,39 @@ + +#ifndef __DEFINES_H +#define __DEFINES_H + +#include +#include +#include +#include + +/* +#if defined(TM4C123GH6PM) + #include "TM4C123GH6PM.h" +#elif defined(TM4C1294NCPDT) + #include "TM4C1294NCPDT.h" +#endif +*/ + + +#define PIN0 0x01 +#define PIN1 0x02 +#define PIN2 0x04 +#define PIN3 0x08 +#define PIN4 0x10 +#define PIN5 0x20 +#define PIN6 0x40 +#define PIN7 0x80 + +#define BIT0 0x01 +#define BIT1 0x02 +#define BIT2 0x04 +#define BIT3 0x08 +#define BIT4 0x10 +#define BIT5 0x20 +#define BIT6 0x40 +#define BIT7 0x80 + + + +#endif diff --git a/ezTivaLib/ez123G.h b/ezTivaLib/ez123G.h new file mode 100755 index 0000000..b8e5b26 --- /dev/null +++ b/ezTivaLib/ez123G.h @@ -0,0 +1,14 @@ +#ifndef __EZ123G_LIB__H +#define __EZ123G_LIB__H + +#include +#include +#include +#include +#include "Defines.h" +#include "ezTimer.h" +#include "ezLCD.h" + +#endif + + diff --git a/ezTivaLib/ez123GLIB.lib b/ezTivaLib/ez123GLIB.lib new file mode 100755 index 0000000000000000000000000000000000000000..2a6f5c7beb649d6ed104248b2d11c88f251e33be GIT binary patch literal 226728 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 z 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 literal 0 HcmV?d00001 diff --git a/ezTivaLib/ezLCD.h b/ezTivaLib/ezLCD.h new file mode 100755 index 0000000..9e60360 --- /dev/null +++ b/ezTivaLib/ezLCD.h @@ -0,0 +1,72 @@ +#ifndef __EZLCD_LIB__H +#define __EZLCD_LIB__H + +#if defined(TM4C123GH6PM) + #include "TM4C123GH6PM.H" + typedef GPIOA_Type GPIO_Port; + typedef GPIOA_Type* PGPIO_Port; +# +#elif defined(TM4C1294NCPDT) + #include "TM4C1294NCPDT.h" + typedef GPIOA_AHB_Type GPIO_Port; + typedef GPIOA_AHB_Type* PGPIO_Port; +#else + #error "The Device NOT specified" +#endif + +#include +#include +#include +#include + +#include // memset +#include "ezTimer.h" + +//typedef GPIOA_AHB_Type GPIO_Port; +//typedef GPIOA_AHB_Type* PGPIO_Port; + + +typedef enum { + PIN_3_0, + PIN_7_4 +} EZLCD_DATAPORT_PIN; + +typedef struct EZOBJ_LCD{ + void* PrivateData; +} EZOBJ_LCD; +typedef EZOBJ_LCD * PEZOBJ_LCD; + +PEZOBJ_LCD ezLCD_Create(void); + +void ezLCD_Connect_DataPort(PEZOBJ_LCD lcd, PGPIO_Port port, EZLCD_DATAPORT_PIN mode); +void ezLCD_Connect_ENPin(PEZOBJ_LCD lcd, PGPIO_Port port, uint8_t enpin); +void ezLCD_Connect_RSPin(PEZOBJ_LCD lcd, PGPIO_Port port, uint8_t rspin); +void ezLCD_Connect_RWPin(PEZOBJ_LCD lcd, PGPIO_Port port, uint8_t rwpin); + +bool ezLCD_Start(PEZOBJ_LCD lcd); +void ezLCD_Enable(PEZOBJ_LCD lcd); +void ezLCD_DisplayOff(PEZOBJ_LCD lcd); +void ezLCD_DisplayOn(PEZOBJ_LCD lcd); + +void ezLCD_ClearDisplay(PEZOBJ_LCD lcd); +void ezLCD_Position(PEZOBJ_LCD lcd, uint8_t row, uint8_t column); +void ezLCD_LoadVerticalBargraphFonts(PEZOBJ_LCD lcd); +void ezLCD_LoadHorizontalBargraphFonts(PEZOBJ_LCD lcd); + +void ezLCD_LoadCustomFonts(PEZOBJ_LCD lcd, uint8_t const customData[]); + +void ezLCD_DrawHorizontalBG(PEZOBJ_LCD lcd, uint8_t row, uint8_t column, uint8_t maxCharacters, uint8_t value); +void ezLCD_DrawVerticalBG(PEZOBJ_LCD lcd, uint8_t row, uint8_t column, uint8_t maxCharacters, uint8_t value); + +void ezLCD_PrintString(PEZOBJ_LCD lcd, char const str[]); +void ezLCD_PrintInt8(PEZOBJ_LCD lcd, uint8_t value); +void ezLCD_PrintInt16(PEZOBJ_LCD lcd, uint16_t value); +void ezLCD_PrintInt32(PEZOBJ_LCD lcd, uint32_t value); +void ezLCD_PrintNumber(PEZOBJ_LCD lcd, uint16_t value); +void ezLCD_Print32Number(PEZOBJ_LCD lcd, uint32_t value); + +#define ezLCD_PrintDecUint16(lcd,x) ezLCD_PrintNumber(lcd,x) +#define ezLCD_PrintHexUint8(lcd,x) ezLCD_PrintInt8(lcd,x) +#define ezLCD_PrintHexUint16(lcd,x) ezLCD_PrintInt16(lcd,x) + +#endif diff --git a/ezTivaLib/ezTimer.h b/ezTivaLib/ezTimer.h new file mode 100755 index 0000000..043a4d4 --- /dev/null +++ b/ezTivaLib/ezTimer.h @@ -0,0 +1,33 @@ +#ifndef __EZ_1294_LIB_H +#define __EZ_1294_LIB_H + +#include +#include +#include +#include +#include "Defines.h" + + + +#if defined(TM4C123GH6PM) + #include "TM4C123GH6PM.h" +#elif defined(TM4C1294NCPDT) + #include "TM4C1294NCPDT.h" +#endif + + +typedef uint32_t clock_t; + +#if defined(TM4C123GH6PM) + void Setup_123G_80MHz(void); +#elif defined(TM4C1294NCPDT) + void Setup_1294_80MHz(void); +#endif + + +void timer_waitMillis(uint32_t millis); +void timer_waitMicros(uint16_t micros); + + + +#endif diff --git a/firstdraft.txt b/firstdraft.txt new file mode 100755 index 0000000..874f67a --- /dev/null +++ b/firstdraft.txt @@ -0,0 +1,183 @@ +#include +#include +#include +#include + +#include "TM4C123GH6PM.h" +#include "ez123G.h" +#include "MyDefines.h" + +char str[100]; + +void Setup_GPIO(void); +uint32_t getWidth(); +uint32_t measureD(void); +void Setup_Timer(void); +void Setup_PWM(void); + +int main(void) +{ + uint16_t i = 0; + + Setup_123G_80MHz(); + Setup_Timer(); + Setup_PWM(); + Setup_GPIO(); + + PEZOBJ_LCD lcd; + lcd = ezLCD_Create(); + ezLCD_Connect_DataPort(lcd, GPIOD, PIN_3_0); + ezLCD_Connect_ENPin(lcd, GPIOE, PIN1); + ezLCD_Connect_RSPin(lcd, GPIOE, PIN2); + ezLCD_Connect_RWPin(lcd, GPIOE, PIN3); + + double time; + double distance; + uint32_t widthArray[3]; + uint32_t avgWidth; + ezLCD_Start(lcd); + ezLCD_LoadVerticalBargraphFonts(lcd); + + +} + +uint32_t getWidth() +{ + uint32_t pulseWidth = 0; + uint32_t *trig = (uint32_t *)(((char*)GPIOF) + (_PIN3 << 2)); + // Set "Trig" pin to Low + *trig = 0x00; + timer_waitMillis(500); // Waiting for 500ms + // Set "Trig" pin to High for 10ns + *trig = 0xFF; + timer_waitMicros(10); // Waiting for 10ns + // Set "Trig" pin to Low + *trig = 0x00; + pulseWidth = measureD(); // Call measureD() to get the delta t on the "echo" pin + // Calculate distance + + return pulseWidth; +} + +uint32_t measureD(void) +{ + uint32_t highEdge,lowEdge; + uint32_t deltaT; + + /*Capture firstEgde i.e. rising edge*/ + //1. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register + TIMER1 -> ICR = 1 << 2; + //2. Waiting for capture rising edge event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while((TIMER1 -> RIS & (1 << 2)) != (1 << 2)){} + //3. Read the highEdge from GPTMTAR (TIMER1->TAR) registers + highEdge = TIMER1 -> TAR; + /*Capture secondEgde i.e. falling edge*/ + //4. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register + TIMER1 -> ICR = 1 << 2; + //5. Waiting for capture falling edge event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while((TIMER1 -> RIS & (1 << 2)) != (1 << 2)){} + //6. Read the lowEdge from GPTMTAR (TIMERa->TAR) registers + lowEdge = TIMER1 -> TAR; + //7. Calculate deltaT = highEdge - lowEdge + // Note: the deltaT must large than zero, cannot be negative value + if(highEdge > lowEdge){ + deltaT = highEdge - lowEdge; + }else{ + deltaT = 0xFFFFFFFF - (lowEdge - highEdge); + } + return deltaT; +} + +void Setup_Timer(void) +{ + //* PF2: T1CCP0 (PCTL=07) both edge (edge-time mode) + + // 1 . Enable Clock for TIMER Module + SYSCTL->RCGCTIMER |= (_TIMER1); + while ((SYSCTL->PRTIMER & (_TIMER1)) != (_TIMER1)) {} + // 2. Disable TIMER + TIMER1->CTL &= ~(_TIMERA_ENABLE); // Disable TimerA & TimerB + // 3. Configure TIMER + TIMER1->CFG = 0x04; // Split into two 16-bit timers + // 4. Configure Timer n Mode: GPTMTAMR + TIMER1->TAMR = (_TIMERA_COUNTDOWN|_TIMERA_EDGE_TIME|_TIMERA_CAPTURE); + // 5. Configure Timer Event Mode: rising-, falling-, or both-edges + TIMER1->CTL &= ~(0x03 << 2); + TIMER1->CTL |= (_TIMERA_BOTH_EDGES); // Both edges + // 6. Configure Load + TIMER1->TAILR = 0xFFFF; + //Set the prescaler to 0xFF + TIMER1->TAPR = 0xFF; + TIMER1->IMR = 0; + // 7. Enable GPTM Timer + TIMER1->CTL |= _TIMERA_ENABLE; // Enable TimerB +} + +void Setup_GPIO(void) +{ + + // GPIO Initialization and Configuration + // 1. Enable Clock to the GPIO Modules (SYSCTL->RCGCGPIO) + SYSCTL->RCGCGPIO |= _PORTD|_PORTE|_PORTF; + // allow time for clock to stabilize (SYSCTL->PRGPIO) + while((SYSCTL->PRGPIO & (_PORTD|_PORTE|_PORTF)) != (_PORTD|_PORTE|_PORTF)){}; + // 2. Unlock PD7 and PF0 on TM4C123G; or PD7 on TM4C1294 (GPIO->LOCK and GPIO->CR) + // 3. GPIO Analog Mode Select (GPIOAMSEL) + GPIOD -> AMSEL = 0x0; + GPIOE -> AMSEL = 0x0; + GPIOF -> AMSEL = 0x0; + // 4. GPIO Port COntrol (GPIOPCTL) + GPIOD -> PCTL = 0x0; + GPIOE -> PCTL = 0x0; + GPIOF -> PCTL = 0x00005750; + // 5. Clear AFSEL bits to 0 to select regular I/O + GPIOD -> AFSEL = 0x0; + GPIOE -> AFSEL = 0x0; + GPIOF -> AFSEL |= _PIN1|_PIN2|_PIN3; + // 6. GPIO Pin Direction (GPIODIR) 0 for input, 1 for output + GPIOD -> DIR |= _PIN0|_PIN1|_PIN2|_PIN3; + GPIOE -> DIR |= _PIN1|_PIN2|_PIN3; + GPIOF -> DIR |= _PIN1|_PIN3; + // 7. Set PUR bits to 1 to enable internal pull-up resistor + // 8. Set DEN bits to 1 to enable data pins + GPIOD -> DEN |= _PIN0|_PIN1|_PIN2|_PIN3; + GPIOE -> DEN |= _PIN1|_PIN2|_PIN3; + GPIOF -> DEN |= _PIN1|_PIN2|_PIN3; + +} + +void Setup_PWM(){ + //PF1 M1PWM5 GEN 2 + //PF3 M1PWM7 GEN 3 + int load = 8; + // 1. Enable Clock for PWM Module 1 + SYSCTL->RCGCPWM |= _PWM_MODULE1; + while((SYSCTL->PRPWM & _PWM_MODULE1)!= _PWM_MODULE1){}; + // 2. Enable and Setup Clock Divider for PWM + SYSCTL->RCC |= (0 << 20); // RCC[20]=1:USEPWMDIV + //SYSCTL->RCC &= ~0x000E0000; // RCC[19:17]=000 PWMDIV + //SYSCTL->RCC |= (_PWMDIV_2 << 17); // RCC[19:17]=0x04 divider=/32 + // 3. Disable PWM Generator 2 + PWM1->_2_CTL &= ~0x01; // Disable PWM Generator 3 + PWM1->_3_CTL &= ~0x01; // Disable PWM Generator 3 + // 4. Config LOAD, CMPn, GENn values + PWM1->_2_LOAD = load; // GEN 2 B PWM 5 PF1 LED + PWM1->_2_CMPB = load/2; + PWM1->_2_GENB = _PWM_RIGHT_ALIG_CMPBD;//0x080C + + PWM1->_3_LOAD = load; // GEN 3 B PWM 7 PF3 PWM OUT + PWM1->_3_CMPB = load/2; + PWM1->_3_GENB = _PWM_RIGHT_ALIG_CMPBD;//0x080C + // 5. Enable PWM Generator 2 + PWM1->_3_CTL |= 0x01; + PWM1->_3_CTL |= 0x01; + // 6. Enable PWM5 Output + PWM1 -> ENABLE |= _PWM5; + PWM1 -> ENABLE |= _PWM7; + + +} \ No newline at end of file diff --git a/measureFreqDutyLCD.c b/measureFreqDutyLCD.c new file mode 100755 index 0000000..a34d0f7 --- /dev/null +++ b/measureFreqDutyLCD.c @@ -0,0 +1,269 @@ +#include +#include +#include +#include + +#include // The Header File for EK-TM4C123GXL LaunchPad +// #include // The Header File for EK-TM4C1294XL LaunchPad +#include "ez123G.h" +#include "MyDefines.h" // Your Definitions for the System Configuration + +#define _TIMER_CFG_1632B_TIMER16B (0x4) +#define _TIMERA_CAPTURE_EVENT_INT_CLR (1 << 2) +#define _TIMERA_CAPTURE_EVENT_INT (1 << 2) +#define _TIMERB_CAPTURE_EVENT_INT_CLR (1 << 10) +#define _TIMERB_CAPTURE_EVENT_INT (1 << 10) + +float SYSTEM_CLOCK_FREQ = ________; + +typedef enum EDGE_EVENT{ + FALLING_EDGE, + RISING_EDGE + +} EDGE_EVENT; + +void Setup_PWM(void); +void Setup_Timer(void); +void Setup_GPIO(void); +void Setup_UART(void); + +uint32_t MeasurePeriod(void); +uint32_t MeasurePulseWidth(void); +void UART_PrintString(char * s); + +typedef struct PWM_CONTROL{ + uint16_t load; + uint16_t cmp; +} PWM_CONTROL; + +PWM_CONTROL Pwm[]={ + {18150, 4628}, + {6665, 3032}, + {12490, 8118}, + {49996, 37497}, + {8328, 2914} +}; + +// On-board switch +uint32_t *Sw = (uint32_t *) (((char*)_____)+ (______ << 2)); + +int main() +{ + PEZOBJ_LCD lcd; + volatile uint32_t T; + volatile uint32_t t; + uint32_t freq; + double duty; + char str[100]; + int idx = 0; + uint8_t i = 0; + bool preSw = true; + uint16_t currSw; + + Setup_123G_80MHz(); // Setup System Clock to 80 MHz + + Setup_PWM(); + Setup_Timer(); + Setup_GPIO(); + + lcd = ezLCD_Create(); + ezLCD_Connect_DataPort(lcd, GPIO____, PIN_3_0); + ezLCD_Connect_ENPin(lcd, GPIO____, PIN7); + ezLCD_Connect_RSPin(lcd, GPIO____, PIN6); + ezLCD_Connect_RWPin(lcd, GPIO____, PIN4); + + ezLCD_Start(lcd); + ezLCD_ClearDisplay(lcd); + + PWM0->_1_CTL &= ~0x01; // Disable PWM Module 0, Generator 1 + PWM1->_3_CTL &= ~0x01; // Disable PWM Module 1, Generator 3 + PWM0->_1_LOAD = Pwm[idx].load; + PWM0->_1_CMPB = Pwm[idx].cmp; + PWM1->_3_LOAD = Pwm[idx].load; + PWM1->_3_CMPB = Pwm[idx].cmp; + PWM0->_1_CTL |= 0x01; // Disable PWM Module 0, Generator 1 + PWM1->_3_CTL |= 0x01; // Disable PWM Module 1, Generator 3 + + while(1){ + + currSw = *Sw; + if (preSw && (!currSw)){ + if (++idx >= (sizeof(Pwm) / sizeof(PWM_CONTROL))) idx = 0; + PWM0->_1_CTL &= ~0x01; // Disable PWM Module 0, Generator 1 + PWM1->_3_CTL &= ~0x01; // Disable PWM Module 1, Generator 3 + PWM0->_1_LOAD = Pwm[idx].load; + PWM0->_1_CMPB = Pwm[idx].cmp; + PWM1->_3_LOAD = Pwm[idx].load; + PWM1->_3_CMPB = Pwm[idx].cmp; + PWM0->_1_CTL |= 0x01; // Disable PWM Module 0, Generator 1 + PWM1->_3_CTL |= 0x01; // Disable PWM Module 1, Generator 3 + timer_waitMillis(100); + } + preSw = currSw; + + T = MeasurePeriod(); + t = MeasurePulseWidth(); + freq = ____________ ; + duty = ____________ ; + sprintf(str, "%02d: f%d = %d Hz ", i, idx, freq); + ezLCD_Position(lcd, 0,0); + ezLCD_PrintString(lcd, str); + sprintf(str, "Duty = %.1f %% ", duty); + ezLCD_Position(lcd, 1,0); + ezLCD_PrintString(lcd, str); + i = (++i) % 100; + timer_waitMillis(500); + } + +} + +void Setup_PWM(void) +{ +ENB + + // 1. Enable Clock for PWM Module + SYSCTL->RCGCPWM |= (_______); + while((SYSCTL->PRPWM & (_______)) != (_______)){}; + // 2. Enable and Setup Clock Divider for PWM + SYSCTL->RCC |= (1 << 20); // RCC[20]=1:USEPWMDIV + SYSCTL->RCC &= ~(0x07 << 17); // RCC[19:17]=000 PWMDIV + SYSCTL->RCC |= (________ << 17); // RCC[19:17]=0x04 divider=/32 + // 3. Disable PWM Generator + // 4. Configure LOAD (Period), CMP (Initial Duty), GEN (PWM Mode) values + // 5. Enable PWM Generator + // 6. Enable PWM Output + +} +void Setup_Timer(void) +{ + // 1 . Enable Clock for TIMER + SYSCTL->RCGCTIMER |= ________; + while ((SYSCTL->PRTIMER & (________)) != (________)) {} + // 2. Disable TIMER + TIMER_->CTL &= ~(________); + // 3. Configure TIMER + TIMER_->CFG = _TIMER_CFG_1632B_TIMER16B; + // 4. Configure Timer n Mode: GPTMTAMR + TIMER_->TAMR = ________; + // 5. Configure Timer Event Mode + TIMER_->CTL &= ~________; + TIMER_->CTL |= ________; + // 6. Configure Load + TIMER_->TAILR = 0xffff; //0x00000000; + //Set the prescaler to 0xff + TIMER_->TAPR = 0xff; + TIMER_->ICR = _TIMERA_CAPTURE_EVENT_INT_CLR; + TIMER_->IMR = 0; + // 7. Enable GPTM Timer + TIMER_->CTL |= ________; // Enable Timer + +} +void Setup_GPIO(void) +{ + + // GPIO Initialization and Configuration + // 1. Enable Clock to the GPIO Modules (SYSCTL->RCGCGPIO) + SYSCTL->RCGCGPIO |= (_______); + // allow time for clock to stabilize (SYSCTL->PRGPIO) + while((SYSCTL->PRGPIO & (_______)) != (_______)){}; + // 2. Unlock PD7 and/or PF0 on TM4C123G (GPIO->LOCK and GPIO->CR) + //GPIOF->LOCK = 0x4C4F434B; + //GPIOF->CR |= _PIN0; + + //GPIOD_AHB->LOCK = 0x4C4F434B; + //while( (GPIOD_AHB->LOCK & 0x01) == 0x01) {}; + //*(((char*)GPIOD_AHB)+0x524) = 0xFF; + + // 3. GPIO Analog Mode Select (GPIOAMSEL) + // 4. GPIO Port COntrol (GPIOPCTL) + // 5. Clear AFSEL bits to 0 to select regular I/O + // 6. GPIO Pin Direction (GPIODIR) 0 for input, 1 for output + // 7. Set PUR bits to 1 to enable internal pull-up resistor + // 8. Set DEN bits to 1 to enable data pins + +} + +uint32_t MeasurePeriod(void) +{ + volatile uint32_t edge1; + volatile uint32_t edge2; + uint32_t load; + + // **** Capture firstEgde i.e. rising edge **** + TIMER_->CTL &= ~(_TIMERA_ENABLE); + TIMER_->CTL &= ~(_TIMERA_EVENT); + TIMER_->CTL |= ________; // Capture on the falling- or rising- edgs + TIMER_->CTL |= _TIMERA_ENABLE; + + //1. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register (CnERIS bit) + TIMER_->ICR = _TIMERA_CAPTURE_EVENT_INT_CLR; + //2. Waiting for capture event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while ((TIMER_->RIS & _TIMERA_CAPTURE_EVENT_INT) != _TIMERA_CAPTURE_EVENT_INT) {}; + //3. Read the capture value from GPTMTAR (TIMER1->TAR) register + edge1 = TIMER_->TAR; + + // **** Capture secondEgde i.e. falling edge **** + //4. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register + TIMER_->ICR = _TIMERA_CAPTURE_EVENT_INT_CLR; + + //5. Waiting for capture falling edge event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while ((TIMER_->RIS & _TIMERA_CAPTURE_EVENT_INT) != _TIMERA_CAPTURE_EVENT_INT) {}; + + //6. Read the capture value from GPTMTAR (TIMERa->TAR) register + edge2 = TIMER_->TAR; + + //7. Calculate deltaT = highEdge - lowEdge + // Note: the deltaT must large than zero, cannot be negative value + + + + +} +uint32_t MeasurePulseWidth(void) +{ + uint32_t edge1; + uint32_t edge2; + static uint32_t load; + + // **** Capture first Rising-Edge **** + TIMER_->CTL &= ~(_TIMERA_ENABLE); + TIMER_->CTL &= ~(_TIMERA_EVENT); + TIMER_->CTL |= ________; // Capture on the Rising-Edge + TIMER_->CTL |= _TIMERA_ENABLE; + + //1. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register + TIMER_->ICR = _TIMERA_CAPTURE_EVENT_INT_CLR; + //2. Waiting for capture event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while ((TIMER_->RIS & _TIMERA_CAPTURE_EVENT_INT) != _TIMERA_CAPTURE_EVENT_INT) {}; + //3. Read the capture value from GPTMTAR (TIMER1->TAR) register + edge1 = TIMER_->TAR; + + TIMER_->CTL &= ~(_TIMERA_EVENT); + TIMER_->CTL |= ________; // Capture on the Falling-Edge + + + // **** Capture second Egde i.e. falling edge **** + //4. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register + TIMER_->ICR = _TIMERA_CAPTURE_EVENT_INT_CLR; + + //5. Waiting for capture falling edge event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while ((TIMER_->RIS & _TIMERA_CAPTURE_EVENT_INT) != _TIMERA_CAPTURE_EVENT_INT) {}; + + //6. Read the capture value from GPTMTAR (TIMERa->TAR) register + edge2 = TIMER_->TAR; + + //7. Calculate deltaT = highEdge - lowEdge + // Note: the deltaT must large than zero, cannot be negative value + + + +} + diff --git a/pwmanalyserfirstdraft.c b/pwmanalyserfirstdraft.c new file mode 100755 index 0000000..b51f418 --- /dev/null +++ b/pwmanalyserfirstdraft.c @@ -0,0 +1,297 @@ +#include +#include +#include +#include + +#include // The Header File for EK-TM4C123GXL LaunchPad +// #include // The Header File for EK-TM4C1294XL LaunchPad +#include "ez123G.h" +#include "MyDefines.h" // Your Definitions for the System Configuration + +#define _TIMER_CFG_1632B_TIMER16B (0x4) +#define _TIMERA_CAPTURE_EVENT_INT_CLR (1 << 2) +#define _TIMERA_CAPTURE_EVENT_INT (1 << 2) +#define _TIMERB_CAPTURE_EVENT_INT_CLR (1 << 10) +#define _TIMERB_CAPTURE_EVENT_INT (1 << 10) + +float SYSTEM_CLOCK_FREQ = 80E6; + +typedef enum EDGE_EVENT{ + FALLING_EDGE, + RISING_EDGE + +} EDGE_EVENT; + +void Setup_PWM(void); +void Setup_Timer(void); +void Setup_GPIO(void); +void Setup_UART(void); + +uint32_t MeasurePeriod(void); +uint32_t MeasurePulseWidth(void); +void UART_PrintString(char * s); + +typedef struct PWM_CONTROL{ + uint16_t load; + uint16_t cmp; +} PWM_CONTROL; + +PWM_CONTROL Pwm[]={ + {18150, 4628}, + {6665, 3032}, + {12490, 8118}, + {49996, 37497}, + {8328, 2914} +}; + +// On-board switch +uint32_t *Sw = (uint32_t *) (((char*)GPIOF)+ (_PIN4 << 2)); + +int main() +{ + PEZOBJ_LCD lcd; + volatile uint32_t T; + volatile uint32_t t; + uint32_t freq; + double duty; + char str[100]; + int idx = 0; + uint8_t i = 0; + bool preSw = true; + uint16_t currSw; + + Setup_123G_80MHz(); // Setup System Clock to 80 MHz + + Setup_PWM(); + Setup_Timer(); + Setup_GPIO(); + + lcd = ezLCD_Create(); + ezLCD_Connect_DataPort(lcd, GPIOD, PIN_3_0); + ezLCD_Connect_ENPin(lcd, GPIOE, PIN1); + ezLCD_Connect_RSPin(lcd, GPIOE, PIN2); + ezLCD_Connect_RWPin(lcd, GPIOE, PIN3); + + ezLCD_Start(lcd); + ezLCD_ClearDisplay(lcd); + + PWM0->_1_CTL &= ~0x01; // Disable PWM Module 0, Generator 1 + PWM1->_3_CTL &= ~0x01; // Disable PWM Module 1, Generator 3 + PWM0->_1_LOAD = Pwm[idx].load; + PWM0->_1_CMPB = Pwm[idx].cmp; + PWM1->_3_LOAD = Pwm[idx].load; + PWM1->_3_CMPB = Pwm[idx].cmp; + PWM0->_1_CTL |= 0x01; // Disable PWM Module 0, Generator 1 + PWM1->_3_CTL |= 0x01; // Disable PWM Module 1, Generator 3 + + while(1){ + + currSw = *Sw; + if (preSw && (!currSw)){ + if (++idx >= (sizeof(Pwm) / sizeof(PWM_CONTROL))) idx = 0; + PWM0->_1_CTL &= ~0x01; // Disable PWM Module 0, Generator 1 + PWM1->_3_CTL &= ~0x01; // Disable PWM Module 1, Generator 3 + PWM0->_1_LOAD = Pwm[idx].load; + PWM0->_1_CMPB = Pwm[idx].cmp; + PWM1->_3_LOAD = Pwm[idx].load; + PWM1->_3_CMPB = Pwm[idx].cmp; + PWM0->_1_CTL |= 0x01; // Disable PWM Module 0, Generator 1 + PWM1->_3_CTL |= 0x01; // Disable PWM Module 1, Generator 3 + timer_waitMillis(100); + } + preSw = currSw; + + T = MeasurePeriod(); + t = MeasurePulseWidth(); + freq = 1 / (T * (1.25E-8)); + duty = (t * 100) / T ; + sprintf(str, "%02d: f%d = %d Hz ", i, idx, freq); + ezLCD_Position(lcd, 0,0); + ezLCD_PrintString(lcd, str); + sprintf(str, "Duty = %.1f %% ", duty); + ezLCD_Position(lcd, 1,0); + ezLCD_PrintString(lcd, str); + i = (++i) % 100; + timer_waitMillis(500); + } + +} + +void Setup_PWM(void) +{ + //PF1 M1PWM5 GEN 2 + //PF3 M1PWM7 GEN 3 + int load = 8; + // 1. Enable Clock for PWM Module 1 + SYSCTL->RCGCPWM |= _PWM_MODULE1; + while((SYSCTL->PRPWM & _PWM_MODULE1)!= _PWM_MODULE1){}; + // 2. Enable and Setup Clock Divider for PWM + SYSCTL->RCC |= (0 << 20); // RCC[20]=1:USEPWMDIV + //SYSCTL->RCC &= ~0x000E0000; // RCC[19:17]=000 PWMDIV + //SYSCTL->RCC |= (_PWMDIV_2 << 17); // RCC[19:17]=0x04 divider=/32 + // 3. Disable PWM Generator 2 + PWM1->_2_CTL &= ~0x01; // Disable PWM Generator 3 + PWM1->_3_CTL &= ~0x01; // Disable PWM Generator 3 + // 4. Config LOAD, CMPn, GENn values + PWM1->_2_LOAD = load; // GEN 2 B PWM 5 PF1 LED + PWM1->_2_CMPB = load/2; + PWM1->_2_GENB = _PWM_RIGHT_ALIG_CMPBD;//0x080C + + PWM1->_3_LOAD = load; // GEN 3 B PWM 7 PF3 PWM OUT + PWM1->_3_CMPB = load/2; + PWM1->_3_GENB = _PWM_RIGHT_ALIG_CMPBD;//0x080C + // 5. Enable PWM Generator 2 + PWM1->_3_CTL |= 0x01; + PWM1->_3_CTL |= 0x01; + // 6. Enable PWM5 Output + PWM1 -> ENABLE |= _PWM5; + PWM1 -> ENABLE |= _PWM7; + +} +void Setup_Timer(void) +{ + // 1 . Enable Clock for TIMER + SYSCTL->RCGCTIMER |= _TIMER1; + while ((SYSCTL->PRTIMER & (_TIMER1)) != (_TIMER1)) {} + // 2. Disable TIMER + TIMER1->CTL &= ~(_TIMERA_ENABLE); + // 3. Configure TIMER + TIMER1->CFG = _TIMER_CFG_1632B_TIMER16B; + // 4. Configure Timer n Mode: GPTMTAMR + TIMER1->TAMR = (_TIMERA_COUNTDOWN|_TIMERA_EDGE_TIME|_TIMERA_CAPTURE); + // 5. Configure Timer Event Mode + TIMER1->CTL &= ~(0x03 << 2); + TIMER1->CTL |= _TIMERA_BOTH_EDGES; + // 6. Configure Load + TIMER1->TAILR = 0xffff; //0x00000000; + //Set the prescaler to 0xff + TIMER1->TAPR = 0xff; + TIMER1->ICR = _TIMERA_CAPTURE_EVENT_INT_CLR; + TIMER1->IMR = 0; + // 7. Enable GPTM Timer + TIMER1->CTL |= _TIMERA_ENABLE; // Enable Timer + +} +void Setup_GPIO(void) +{ + + // GPIO Initialization and Configuration + // 1. Enable Clock to the GPIO Modules (SYSCTL->RCGCGPIO) + SYSCTL->RCGCGPIO |= _PORTD|_PORTE|_PORTF; + // allow time for clock to stabilize (SYSCTL->PRGPIO) + while((SYSCTL->PRGPIO & (_PORTD|_PORTE|_PORTF)) != (_PORTD|_PORTE|_PORTF)){}; + // 2. Unlock PD7 and PF0 on TM4C123G; or PD7 on TM4C1294 (GPIO->LOCK and GPIO->CR) + // 3. GPIO Analog Mode Select (GPIOAMSEL) + GPIOD -> AMSEL = 0x0; + GPIOE -> AMSEL = 0x0; + GPIOF -> AMSEL = 0x0; + // 4. GPIO Port Control (GPIOPCTL) + GPIOD -> PCTL = 0x0; + GPIOE -> PCTL = 0x0; + GPIOF -> PCTL = 0x00005750; + // 5. Clear AFSEL bits to 0 to select regular I/O + GPIOD -> AFSEL = 0x0; + GPIOE -> AFSEL = 0x0; + GPIOF -> AFSEL |= _PIN1|_PIN2|_PIN3; + // 6. GPIO Pin Direction (GPIODIR) 0 for input, 1 for output + GPIOD -> DIR |= _PIN0|_PIN1|_PIN2|_PIN3; + GPIOE -> DIR |= _PIN1|_PIN2|_PIN3; + GPIOF -> DIR |= _PIN1|_PIN3; + // 7. Set PUR bits to 1 to enable internal pull-up resistor + GPIOF -> PUR |= _PIN4; + // 8. Set DEN bits to 1 to enable data pins + GPIOD -> DEN |= _PIN0|_PIN1|_PIN2|_PIN3; + GPIOE -> DEN |= _PIN1|_PIN2|_PIN3; + GPIOF -> DEN |= _PIN1|_PIN2|_PIN3|_PIN4; +} + +uint32_t MeasurePeriod(void) +{ + volatile uint32_t edge1; + volatile uint32_t edge2; + uint32_t load; + + // **** Capture firstEgde i.e. rising edge **** + TIMER1->CTL &= ~(_TIMERA_ENABLE); + TIMER1->CTL &= ~(0x03); + TIMER1->CTL |= _TIMERA_POSITIVE_EDGE; // Capture on the falling- or rising- edgs + TIMER1->CTL |= _TIMERA_ENABLE; + + //1. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register (CnERIS bit) + TIMER1->ICR = _TIMERA_CAPTURE_EVENT_INT_CLR; + //2. Waiting for capture event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while ((TIMER1->RIS & _TIMERA_CAPTURE_EVENT_INT) != _TIMERA_CAPTURE_EVENT_INT) {}; + //3. Read the capture value from GPTMTAR (TIMER1->TAR) register + edge1 = TIMER1->TAR; + + // **** Capture secondEgde i.e. falling edge **** + //4. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register + TIMER1->ICR = _TIMERA_CAPTURE_EVENT_INT_CLR; + + //5. Waiting for capture falling edge event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while ((TIMER1->RIS & _TIMERA_CAPTURE_EVENT_INT) != _TIMERA_CAPTURE_EVENT_INT) {}; + + //6. Read the capture value from GPTMTAR (TIMERa->TAR) register + edge2 = TIMER1->TAR; + + //7. Calculate deltaT = highEdge - lowEdge + // Note: the deltaT must large than zero, cannot be negative value + if(edge1 > edge2){ + return edge1 - edge2; + }else{ + return (0xFFFFFFFF - (edge2 - edge1)); + } +} + +uint32_t MeasurePulseWidth(void) +{ + uint32_t edge1; + uint32_t edge2; + static uint32_t load; + + // **** Capture first Rising-Edge **** + TIMER1->CTL &= ~(_TIMERA_ENABLE); + TIMER1->CTL &= ~(0x03); + TIMER1->CTL |= _TIMERA_POSITIVE_EDGE; // Capture on the Rising-Edge + TIMER1->CTL |= _TIMERA_ENABLE; + + //1. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register + TIMER1->ICR = _TIMERA_CAPTURE_EVENT_INT_CLR; + //2. Waiting for capture event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while ((TIMER1->RIS & _TIMERA_CAPTURE_EVENT_INT) != _TIMERA_CAPTURE_EVENT_INT) {}; + //3. Read the capture value from GPTMTAR (TIMER1->TAR) register + edge1 = TIMER1->TAR; + + TIMER1->CTL &= ~(0x03); + TIMER1->CTL |= _TIMERA_NEGATIVE_EDGE; // Capture on the Falling-Edge + + + // **** Capture second Egde i.e. falling edge **** + //4. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register + TIMER1->ICR = _TIMERA_CAPTURE_EVENT_INT_CLR; + + //5. Waiting for capture falling edge event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while ((TIMER1->RIS & _TIMERA_CAPTURE_EVENT_INT) != _TIMERA_CAPTURE_EVENT_INT) {}; + + //6. Read the capture value from GPTMTAR (TIMERa->TAR) register + edge2 = TIMER1->TAR; + + //7. Calculate deltaT = highEdge - lowEdge + // Note: the deltaT must large than zero, cannot be negative value + if(edge1 > edge2){ + return edge1 - edge2; + }else{ + return (0xFFFFFFFF - (edge2 - edge1)); + } + + +} + diff --git a/pwmmeasurer/MyDefines.h b/pwmmeasurer/MyDefines.h new file mode 100755 index 0000000..146c609 --- /dev/null +++ b/pwmmeasurer/MyDefines.h @@ -0,0 +1,65 @@ +#ifndef __MYDEFINES_H +#define __MYDEFINES_H + +#define _PIN0 0x01 +#define _PIN1 0x02 +#define _PIN2 0x04 +#define _PIN3 0x08 +#define _PIN4 0x10 +#define _PIN5 0x20 +#define _PIN6 0x40 +#define _PIN7 0x80 + +#define _PORTA 0x0001 +#define _PORTB 0x0002 +#define _PORTC 0x0004 +#define _PORTD 0x0008 +#define _PORTE 0x0010 +#define _PORTF 0x0020 + + +#define _PWM_MODULE0 0x01 +#define _PWM_MODULE1 0x02 + +#define _PWM0 0x01 +#define _PWM1 0x02 +#define _PWM2 0x04 +#define _PWM3 0x08 +#define _PWM4 0x10 +#define _PWM5 0x20 +#define _PWM6 0x40 +#define _PWM7 0x80 + +#define _PWMDIV_2 0x0 +#define _PWMDIV_4 0x1 +#define _PWMDIV_8 0x2 +#define _PWMDIV_16 0x3 +#define _PWMDIV_32 0x4 +#define _PWMDIV_64 0x5 + +#define _PWM_LEFT_ALIG_CMPAD ((0x02 << 6) | (0x03 << 2)) +#define _PWM_LEFT_ALIG_CMPBD ((0x02 << 10) | (0x03 << 2)) + +#define _PWM_RIGHT_ALIG_CMPAD ((0x03 << 6) | (0x02 << 2)) +#define _PWM_RIGHT_ALIG_CMPBD ((0x03 << 10) | (0x02 << 2)) + +#define _TIMER0 0x01 +#define _TIMER1 0x02 +#define _TIMER2 0x04 +#define _TIMER3 0x08 +#define _TIMER4 0x10 +#define _TIMER5 0x20 +#define _TIMER6 0x40 +#define _TIMER7 0x80 + +#define _TIMERA_ENABLE (1 << 0) +#define _TIMERB_ENABLE (1 << 8) +#define _TIMERA_COUNTUP (1 << 4) +#define _TIMERA_COUNTDOWN (0 << 4) +#define _TIMERA_CAPTURE 0x03 +#define _TIMERA_EDGE_TIME (1 << 2) +#define _TIMERA_POSITIVE_EDGE 0 +#define _TIMERA_NEGATIVE_EDGE (1 << 2) +#define _TIMERA_BOTH_EDGES (3 << 2) + +#endif \ No newline at end of file diff --git a/pwmmeasurer/main.c b/pwmmeasurer/main.c new file mode 100755 index 0000000..fe78b98 --- /dev/null +++ b/pwmmeasurer/main.c @@ -0,0 +1,314 @@ +#include +#include +#include +#include + +#include "TM4C123GH6PM.h" // The Header File for EK-TM4C123GXL LaunchPad +#include "ez123G.h" +#include "MyDefines.h" // Your Definitions for the System Configuration + +#define _TIMER_CFG_1632B_TIMER16B (0x4) +#define _TIMERA_CAPTURE_EVENT_INT_CLR (1 << 2) +#define _TIMERA_CAPTURE_EVENT_INT (1 << 2) +#define _TIMERB_CAPTURE_EVENT_INT_CLR (1 << 10) +#define _TIMERB_CAPTURE_EVENT_INT (1 << 10) + +float SYSTEM_CLOCK_FREQ = 80E6; + +typedef enum EDGE_EVENT{ + FALLING_EDGE, + RISING_EDGE + +} EDGE_EVENT; + +void Setup_PWM(void); +void Setup_Timer(void); +void Setup_GPIO(void); + +uint32_t MeasurePeriod(void); +uint32_t MeasurePulseWidth(void); + +typedef struct PWM_CONTROL{ + uint16_t load; + uint16_t cmp; +} PWM_CONTROL; + +PWM_CONTROL Pwm[]={ + {18150, 4628}, + {6665, 3032}, + {12490, 8118}, + {49996, 37497}, + {8328, 2914} +}; + +// On-board switch +uint32_t *Sw = (uint32_t *) (((char*)GPIOF)+ (_PIN4 << 2)); + +int main() +{ + PEZOBJ_LCD lcd; + volatile uint32_t T; + volatile uint32_t t; + uint32_t freq; + double duty; + char str[100]; + int idx = 0; + uint8_t i = 0; + bool preSw = true; + uint16_t currSw; + + Setup_123G_80MHz(); // Setup System Clock to 80 MHz + + Setup_PWM(); + Setup_Timer(); + Setup_GPIO(); + + lcd = ezLCD_Create(); + ezLCD_Connect_DataPort(lcd, GPIOD, PIN_3_0); + ezLCD_Connect_ENPin(lcd, GPIOE, PIN1); + ezLCD_Connect_RSPin(lcd, GPIOE, PIN2); + ezLCD_Connect_RWPin(lcd, GPIOE, PIN3); + + ezLCD_Start(lcd); + ezLCD_LoadVerticalBargraphFonts(lcd); + ezLCD_ClearDisplay(lcd); + //ezLCD_PrintString(lcd, "HELLO WORLD"); + + PWM0->_1_CTL &= ~0x01; // Disable PWM Module 0, Generator 1 + PWM1->_3_CTL &= ~0x01; // Disable PWM Module 1, Generator 3 + PWM0->_1_LOAD = Pwm[idx].load; + PWM0->_1_CMPB = Pwm[idx].cmp; + PWM1->_3_LOAD = Pwm[idx].load; + PWM1->_3_CMPB = Pwm[idx].cmp; + PWM0->_1_CTL |= 0x01; // Disable PWM Module 0, Generator 1 + PWM1->_3_CTL |= 0x01; // Disable PWM Module 1, Generator 3 + + while(1){ + + currSw = *Sw; + if (preSw && (!currSw)){ + if (++idx >= (sizeof(Pwm) / sizeof(PWM_CONTROL))) idx = 0; + PWM0->_1_CTL &= ~0x01; // Disable PWM Module 0, Generator 1 + PWM1->_3_CTL &= ~0x01; // Disable PWM Module 1, Generator 3 + PWM0->_1_LOAD = Pwm[idx].load; + PWM0->_1_CMPB = Pwm[idx].cmp; + PWM1->_3_LOAD = Pwm[idx].load; + PWM1->_3_CMPB = Pwm[idx].cmp; + PWM0->_1_CTL |= 0x01; // Disable PWM Module 0, Generator 1 + PWM1->_3_CTL |= 0x01; // Disable PWM Module 1, Generator 3 + timer_waitMillis(100); + } + preSw = currSw; + + T = MeasurePeriod(); + t = MeasurePulseWidth(); + freq = 1 / (T * (1.25E-8)); + duty = (t * 100)/T ; + sprintf(str, "%02d: f%d = %d Hz ", i, idx, freq); + ezLCD_Position(lcd, 0,0); + ezLCD_PrintString(lcd, str); + sprintf(str, "Duty = %.1f %% ", duty); + ezLCD_Position(lcd, 1,0); + ezLCD_PrintString(lcd, str); + i = (++i) % 100; + timer_waitMillis(500); + } + +} + +void Setup_PWM(void) +{ + // M0 GEN 1 B PWM 3 PB5 PWM + // M1 GEN 3 B PWM 7 PF3 LED + + // 1. Enable Clock for PWM Module + SYSCTL->RCGCPWM |= (_PWM_MODULE0|_PWM_MODULE1); + while((SYSCTL->PRPWM & (_PWM_MODULE0|_PWM_MODULE1)) != (_PWM_MODULE0|_PWM_MODULE1)){}; + // 2. Enable and Setup Clock Divider for PWM + SYSCTL->RCC |= (1 << 20); // RCC[20]=1:USEPWMDIV + SYSCTL->RCC &= ~(0x07 << 17); // RCC[19:17]=000 PWMDIV + SYSCTL->RCC |= (_PWMDIV_8 << 17); // RCC[19:17]=0x04 divider=/32 + // 3. Disable PWM Generator + PWM0->_1_CTL &= ~0x01; // Disable PWM Generator 1 + PWM1->_3_CTL &= ~0x01; // Disable PWM Generator 3 + // 4. Configure LOAD (Period), CMP (Initial Duty), GEN (PWM Mode) values + PWM0->_1_LOAD = 18150; + PWM0->_1_CMPB = 4628; + PWM1->_3_LOAD = 18150; + PWM1->_3_CMPB = 4628; + + PWM0 -> _1_GENB = _PWM_RIGHT_ALIG_CMPBD; + PWM1 -> _3_GENB = _PWM_RIGHT_ALIG_CMPBD; + // 5. Enable PWM Generator + PWM0->_1_CTL |= 0x01; + PWM1->_3_CTL |= 0x01; + // 6. Enable PWM Output + PWM0 -> ENABLE = _PWM3; + PWM1 -> ENABLE = _PWM7; + + +} +void Setup_Timer(void) +{ + //PF2 T1CCP0 + + // 1 . Enable Clock for TIMER + SYSCTL->RCGCTIMER |= _TIMER1; + while ((SYSCTL->PRTIMER & (_TIMER1)) != (_TIMER1)) {} + // 2. Disable TIMER + TIMER1->CTL &= ~(_TIMERA_ENABLE); + // 3. Configure TIMER + TIMER1->CFG = _TIMER_CFG_1632B_TIMER16B; + // 4. Configure Timer n Mode: GPTMTAMR + TIMER1->TAMR = (_TIMERA_COUNTDOWN|_TIMERA_EDGE_TIME|_TIMERA_CAPTURE); + // 5. Configure Timer Event Mode + TIMER1->CTL &= ~(0x03 << 2); + TIMER1->CTL |= _TIMERA_BOTH_EDGES; + // 6. Configure Load + TIMER1->TAILR = 0xffff; //0x00000000; + //Set the prescaler to 0xff + TIMER1->TAPR = 0xff; + TIMER1->ICR = _TIMERA_CAPTURE_EVENT_INT_CLR; + TIMER1->IMR = 0; + // 7. Enable GPTM Timer + TIMER1->CTL |= _TIMERA_ENABLE; // Enable Timer + +} +void Setup_GPIO(void) +{ + + // GPIO Initialization and Configuration + // 1. Enable Clock to the GPIO Modules (SYSCTL->RCGCGPIO) + SYSCTL->RCGCGPIO |= (_PORTB|_PORTD|_PORTE|_PORTF); + // allow time for clock to stabilize (SYSCTL->PRGPIO) + while((SYSCTL->PRGPIO & (_PORTB|_PORTD|_PORTE|_PORTF)) != (_PORTB|_PORTD|_PORTE|_PORTF)){}; + // 2. Unlock PD7 and/or PF0 on TM4C123G (GPIO->LOCK and GPIO->CR) + //GPIOF->LOCK = 0x4C4F434B; + //GPIOF->CR |= _PIN0; + + //GPIOD_AHB->LOCK = 0x4C4F434B; + //while( (GPIOD_AHB->LOCK & 0x01) == 0x01) {}; + //*(((char*)GPIOD_AHB)+0x524) = 0xFF; + + // 3. GPIO Analog Mode Select (GPIOAMSEL) + GPIOB -> AMSEL = 0x00; + GPIOD -> AMSEL = 0x00; + GPIOE -> AMSEL = 0x00; + GPIOF -> AMSEL = 0x00; + // 4. GPIO Port COntrol (GPIOPCTL) + GPIOB -> PCTL = 0x00400000; + GPIOD -> PCTL = 0x00; + GPIOE -> PCTL = 0x00; + GPIOF -> PCTL = 0x00005700; + // 5. Clear AFSEL bits to 0 to select regular I/O + GPIOB -> AFSEL |= _PIN5; + GPIOD -> AFSEL = 0x0; + GPIOE -> AFSEL = 0x0; + GPIOF -> AFSEL |= (_PIN2|_PIN3); + // 6. GPIO Pin Direction (GPIODIR) 0 for input, 1 for output + GPIOB -> DIR |= (_PIN5); + GPIOD -> DIR |= (_PIN0|_PIN1|_PIN2|_PIN3); + GPIOE -> DIR |= (_PIN1|_PIN2|_PIN3); + GPIOF -> DIR |= (_PIN3); + // 7. Set PUR bits to 1 to enable internal pull-up resistor + GPIOF -> PUR |= (_PIN4); + // 8. Set DEN bits to 1 to enable data pins + GPIOB -> DEN |= (_PIN5); + GPIOD -> DEN |= (_PIN0|_PIN1|_PIN2|_PIN3); + GPIOE -> DEN |= (_PIN1|_PIN2|_PIN3); + GPIOF -> DEN |= (_PIN2|_PIN3|_PIN4); + +} + +uint32_t MeasurePeriod(void) +{ + volatile uint32_t edge1; + volatile uint32_t edge2; + uint32_t load; + + // **** Capture firstEgde i.e. rising edge **** + TIMER1->CTL &= ~(_TIMERA_ENABLE); + TIMER1->CTL &= ~(0x03 << 2); + TIMER1->CTL |= _TIMERA_POSITIVE_EDGE; // Capture on the falling- or rising- edgs + TIMER1->CTL |= _TIMERA_ENABLE; + + //1. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register (CnERIS bit) + TIMER1->ICR = _TIMERA_CAPTURE_EVENT_INT_CLR; + //2. Waiting for capture event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while ((TIMER1->RIS & _TIMERA_CAPTURE_EVENT_INT) != _TIMERA_CAPTURE_EVENT_INT) {}; + //3. Read the capture value from GPTMTAR (TIMER1->TAR) register + edge1 = TIMER1->TAR; + + // **** Capture secondEgde i.e. falling edge **** + //4. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register + TIMER1->ICR = _TIMERA_CAPTURE_EVENT_INT_CLR; + + //5. Waiting for capture falling edge event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while ((TIMER1->RIS & _TIMERA_CAPTURE_EVENT_INT) != _TIMERA_CAPTURE_EVENT_INT) {}; + + //6. Read the capture value from GPTMTAR (TIMERa->TAR) register + edge2 = TIMER1->TAR; + + //7. Calculate deltaT = highEdge - lowEdge + // Note: the deltaT must large than zero, cannot be negative value + if(edge1 > edge2){ + return edge1 - edge2; + }else{ + return (0xFFFFFFFF - (edge2 - edge1)); + } + + + +} +uint32_t MeasurePulseWidth(void) +{ + uint32_t edge1; + uint32_t edge2; + static uint32_t load; + + // **** Capture first Rising-Edge **** + TIMER1->CTL &= ~(_TIMERA_ENABLE); + TIMER1->CTL &= ~(0x03 << 2); + TIMER1->CTL |= _TIMERA_POSITIVE_EDGE; // Capture on the Rising-Edge + TIMER1->CTL |= _TIMERA_ENABLE; + + //1. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register + TIMER1->ICR = _TIMERA_CAPTURE_EVENT_INT_CLR; + //2. Waiting for capture event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while ((TIMER1->RIS & _TIMERA_CAPTURE_EVENT_INT) != _TIMERA_CAPTURE_EVENT_INT) {}; + //3. Read the capture value from GPTMTAR (TIMER1->TAR) register + edge1 = TIMER1->TAR; + + TIMER1->CTL &= ~(0x03 << 2); + TIMER1->CTL |= _TIMERA_NEGATIVE_EDGE; // Capture on the Falling-Edge + + + // **** Capture second Egde i.e. falling edge **** + //4. Clear GPTM Timer A Capture Mode Event by writing 1 to + // corresponding bit on GPTMICR (TIMER1->ICR) register + TIMER1->ICR = _TIMERA_CAPTURE_EVENT_INT_CLR; + + //5. Waiting for capture falling edge event by check the GPTM Raw Interrupt Status + // GPTMRIS (TIMER1->RIS) register + while ((TIMER1->RIS & _TIMERA_CAPTURE_EVENT_INT) != _TIMERA_CAPTURE_EVENT_INT) {}; + + //6. Read the capture value from GPTMTAR (TIMERa->TAR) register + edge2 = TIMER1->TAR; + + //7. Calculate deltaT = highEdge - lowEdge + // Note: the deltaT must large than zero, cannot be negative value + if(edge1 > edge2){ + return edge1 - edge2; + }else{ + return (0xFFFFFFFF - (edge2 - edge1)); + } + + +} + diff --git a/servo/MyDefines.h b/servo/MyDefines.h new file mode 100755 index 0000000..fb99053 --- /dev/null +++ b/servo/MyDefines.h @@ -0,0 +1,43 @@ +#ifndef __MYDEFINES_H +#define __MYDEFINES_H + +#define _PIN0 0x01 +#define _PIN1 0x02 +#define _PIN2 0x04 +#define _PIN3 0x08 +#define _PIN4 0x10 +#define _PIN5 0x20 +#define _PIN6 0x40 +#define _PIN7 0x80 + +#define _PORTA 0x0001 +#define _PORTB 0x0002 +#define _PORTC 0x0004 +#define _PORTD 0x0008 +#define _PORTE 0x0010 +#define _PORTF 0x0020 + + +#define _PWM_MODULE0 0x01 +#define _PWM_MODULE1 0x02 + +#define _PWM0 0x01 +#define _PWM1 0x02 +#define _PWM2 0x04 +#define _PWM3 0x08 +#define _PWM4 0x10 +#define _PWM5 0x20 +#define _PWM6 0x40 +#define _PWM7 0x80 + +#define _PWMDIV_2 0x0 +#define _PWMDIV_4 0x1 +#define _PWMDIV_8 0x2 +#define _PWMDIV_16 0x3 +#define _PWMDIV_32 0x4 +#define _PWMDIV_64 0x5 + +#define _PWM_LEFT_ALIG_CMPAD ((0x02 << 6) | (0x03 << 2)) +#define _PWM_LEFT_ALIG_CMPBD ((0x02 << 10) | (0x03 << 2)) + +#endif \ No newline at end of file diff --git a/servo/main.c b/servo/main.c new file mode 100755 index 0000000..8fc4a17 --- /dev/null +++ b/servo/main.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include "MyDefines.h" + +#include "TM4C123GH6PM.h" + +void SetupPWM(void); +void SetupGPIO(void); + +void Delay(int s) +{ + volatile int i, j; + for (i = 0; i < s; i++){ + for(j = 0; j < 3180; j++){}} +} + +#define CMP_0_5MS 19500 +#define CMP_1_5MS 18500 +#define CMP_2_5MS 17500 +#define TO_RIGHT 0 +int main() +{ + uint16_t cmp = CMP_1_5MS; + bool dir = TO_RIGHT; + SetupPWM(); + SetupGPIO(); + + while(1){ + if(dir == TO_RIGHT){ + cmp += 10; + if( cmp >= CMP_0_5MS){ + cmp = CMP_0_5MS; + dir = !dir; + } + }else{ + cmp -= 10; + if(cmp <= CMP_2_5MS){ + cmp = CMP_2_5MS; + dir = !dir; + } + } + PWM1->_3_CMPB = cmp; + Delay(10); + } +} + +void SetupGPIO(){ + // Config for GPIO + // 1. Enable Clock on GPIOF + SYSCTL->RCGCGPIO = _PORTF; + // allow time for clock to stabilize + while((SYSCTL->PRGPIO & _PORTF) != _PORTF){}; + // 2. Unlock GPIO + // 3. Clear AMSEL to disable analog + GPIOF -> AMSEL = 0x0; + // 4. Config PCTL to select GPIO + GPIOF -> PCTL = 0x00005000; + // 5. Set DIR to 0 for input, 1 for output + GPIOF -> DIR = _PIN3; + // 6. Enable AFSEL bits to 1 + GPIOF -> AFSEL = _PIN3; + // 7. Set PUE bits to 1 to enable internal pull-up + // 8. Set DEN bits to 1 to enable data pins + GPIOF -> DEN = _PIN3; +} + +void SetupPWM(void) +{ + // 1. Enable Clock for PWM Module 1 + SYSCTL->RCGCPWM |= _PWM_MODULE1; + while((SYSCTL->PRPWM & _PWM_MODULE1)==0){}; + // 2. Enable and Setup Clock Divider for PWM + SYSCTL->RCC |= (1 << 20); // RCC[20]=1:USEPWMDIV + SYSCTL->RCC &= ~0x000E0000; // RCC[19:17]=000 PWMDIV + SYSCTL->RCC |= (_PWMDIV_16 << 17); // RCC[19:17]=0x04 divider=/32 + // 3. Disable PWM Generator 2 + PWM1->_3_CTL &= ~0x01; // Disable PWM Generator 2 + // 4. Config LOAD, CMPn, GENn values + PWM1->_3_LOAD = 20000; // GEN 3 B PWM 7 PF3 MOTOR + PWM1->_3_CMPB = 18500; + PWM1->_3_GENB = (0x02 << 10 ) | (0x03 <<2);//0x080C + // 5. Enable PWM Generator 3 + PWM1->_3_CTL |= 0x01; + // 6. Enable PWM7 Output + PWM1 -> ENABLE |= _PWM7; +} \ No newline at end of file