-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
198 lines (165 loc) · 7.45 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*
* File: main.c
* Author: rschaub
*
* PIC16F1825
* _______
* VDD ---|1 14|--- VSS
* ---|2 13|---
* ---|3 12|---
* ---|4 11|--- potentiometer "input"
* ---|5 10|---
* ---|6 9|---
* pwm out ---|7_______8|--- "on" light
*
* This program drives a buzzer at specific frequencies to test the loudness
* for each frequency
* Created on April 17, 2019, 1:25 PM
*/
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = ON // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable (PWRT enabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF // Internal/External Switchover (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF // PLL Enable (4x PLL disabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = OFF // Low-Voltage Programming Enable (Low-voltage programming disabled)
#include "buzzer_tester.h"
unsigned int adc_result = 0; //this is where the ADC value will be stored
char out_state = 0;
int tmp = 0;
void adc_init(void){
// sets up the ADC
ADCON0bits.ADON = 0; //turn ADC off for config
ADCON1bits.ADPREF = 0b00; //ADC positive reference is set to VDD
ADCON1bits.ADNREF = 0; //ADC negative reference is set to VSS
ADCON0bits.CHS = 0b00010; //selecting the AN2 analog channel
ADCON1bits.ADCS = 0b100; //ADC clock set to FOSC/4
ADCON1bits.ADFM = 1; //ADC result is right justified
ADCON0bits.ADON = 1; //turn ADC on
}
int ADC_Convert(void){
ADCON0bits.GO_nDONE = 1; //start ADC
while (ADCON0bits.GO_nDONE == 1); //wait for ADC to finish
return (ADRESL + (ADRESH *256));
}
void timer2_init(void) {
// timer2 is used to drive the output frequency to the buzzer via the PWM
// driver the clock source is the system clock / 4, which is 1MHz
T2CONbits.TMR2ON = 0; //turn off timer2 for configuration
PIR1bits.TMR2IF = 0; //reset Timer2 overflow interrupt flag
T2CONbits.T2CKPS = 0b00; //pre-scaler set to 1:1
T2CONbits.T2OUTPS = 0b0010; //post-scaler set to 1:3
TMR2 = 0; //clear timer4
PR2 = 255; //set timer4 match reg to a "nice" value
// the above sets the interrupt freq to ((((1MHz) / 1) / 255) / 3) = ~1.3kHz
T2CONbits.TMR2ON = 1; //turn on Timer2
return;
}
void timer4_init(void) {
// timer4 is used to clock the update of the PWM frequency
// driver the clock source is the system clock / 4, which is 1MHz
T4CONbits.TMR4ON = 0; //turn off timer4 for configuration
PIR3bits.TMR4IF = 0; //reset Timer4 overflow interrupt flag
T4CONbits.T4CKPS = 0b11; //pre-scaler set to 1:64
T4CONbits.T4OUTPS = 0b0111; //post-scaler set to 1:8
TMR4 = 0; //clear timer4
PR4 = 195; //set timer4 match reg to a "nice" value
// the above sets the interrupt freq to ((((1MHz) / 64) / 195) / 8) = 10.02Hz
T4CONbits.TMR4ON = 1; //turn on Timer4
return;
}
void tmr2_interrupt_handler(void){
out_state = ~out_state;
PORTCbits.RC3 = out_state;
return;
}
void tmr4_interrupt_handler(void){
// if the knob is all the way left, let the output frequency be 1kHz. else
// let the output frequency be 800Hz
tmp = adc_result / 128;
switch (tmp) {
case 0:
PR2 = 238; // 700Hz
break;
case 1:
PR2 = 208; // 801Hz
break;
case 2:
PR2 = 167; // 998Hz
break;
case 3:
PR2 = 151; // 1104Hz
break;
case 4:
PR2 = 139; // 1199Hz
break;
case 5:
PR2 = 111; // 1501Hz
break;
case 6:
PR2 = 83; // 2008Hz
break;
case 7:
PR2 = 55; // 3030Hz
break;
default: PR2 = 255; // 654Hz
}
return;
}
void main(void) {
// configure the internal program clock to run at 4MHz
OSCCONbits.SPLLEN = 0b0; // 4xPLL disabled (also disable by config word)
OSCCONbits.IRCF = 0b1101; // HFINTOSC set to 4MHz
OSCCONbits.SCS = 0b00; // clock source set by FOSC config word
// configure the watchdog timer
WDTCONbits.WDTPS = 0b01011; //set to 2s timer
// configure the inputs and outputs
TRISAbits.TRISA2 = 1; //set RA2 (pin 11) as input (for analog input)
TRISCbits.TRISC0 = 0; //set RC0 (pin 10) as output
TRISCbits.TRISC1 = 0; //set RC1 (pin 9) as output
TRISCbits.TRISC2 = 0; //set RC2 (pin 8) as output
TRISCbits.TRISC3 = 0; //set RC3 (pin 7) as an output
ANSELA = 0b00000100; //set RA2 (pin 11) as an analog input (AN2 channel))
ANSELC = 0b00000000; //nothing on port C is an analog input
// turn on interrupts
PIE1bits.TMR2IE = 1; //enable timer2 to PR2 match interrupt
PIE3bits.TMR4IE = 1; //enable timer4 to PR4 match interrupt
INTCONbits.PEIE = 1; //enable peripheral interrupts
INTCONbits.GIE = 1; //general interrupts enabled
// configure the timers, the adc, and the pwm
timer2_init();
timer4_init();
adc_init();
//pwm_init();
PORTCbits.RC2 = 1; //just to tell the user that the program started
while(1){
adc_result = ADC_Convert();
CLRWDT(); //clear the Watchdog Timer to keep the PIC from
//resetting. sadly the program won't get here
//if the button is pressed...
}
return;
}
void interrupt ISR(void){
// check for timer2 overflow interrupt
if(PIR1bits.TMR2IF == 1){
tmr2_interrupt_handler();
PIR1bits.TMR2IF = 0; //reset the interrupt flag
}
// check for timer4 overflow interrupt
if(PIR3bits.TMR4IF == 1){
tmr4_interrupt_handler();
PIR3bits.TMR4IF = 0; //reset the interrupt flag
}
return;
}