Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define F_CPU 16000000
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <stdio.h>
- #include <avr/delay.h>
- #define ch0 0x00
- #define internalVoltage 0x03
- #define PWM_8Scalar 0x02
- #define PWM_noScalar 0x01
- #define PWM_WGM_11_10 0x03
- #define PWM_WGM_13_12 0x00
- #define ICP_WGM_11_10 0x00
- #define ICP_WGM_13_12 0x01
- #define ICP_Toggle 0x01
- #define ICP_OC_High 0x03
- #define PWM_nonInvert 0x02
- #define PWM_timerOVR 0x01
- #define ADC_timer1OVR_trigger 0x06
- #define ADC_autoTrigger_en en
- #define rxEN 1
- #define txIEN 1
- #define drIEN 1
- #define txEN 1
- #define eightBit 0x03
- #define async 0x00
- #define sync 0x01
- #define noParity 0x00
- #define oneStop 0x00
- #define twoStop 0x01
- #define chSize8 0x03
- #define BAUD 9600
- #define BAUDPRESCALAR ((F_CPU/(BAUD))/16 - 1) //Register Values
- #define RPM_conversion ((float)(60)/(192))
- #define ICES (1U)
- #define true 0x01U
- #define false 0x00U
- #define bool unsigned int
- #define en 0x01
- uint16_t readADC();
- void adcStartConvertion();
- void initADC(uint8_t adcCh, uint8_t adcRef, uint8_t leftShift, uint8_t autoTriggerEn, uint8_t autoTrigger);
- void initTimer1PWM();
- void initTimer3Delay_100ms();
- void initINT0();
- void initUART(uint8_t umsel, uint8_t upm, uint8_t usbs, uint8_t ucsz);
- float calculateRPM_x1();
- float calculateRPM_x2();
- void convert_float_to_string(float floatNum);
- void sendString_UART();
- void startPWM1();
- void stopPWM1();
- void dsINT0();
- volatile bool ICP_BUSY;
- volatile unsigned int adcBUSY;
- static volatile char* dataString;
- static char charConversion[20];
- volatile bool uart_BUSY;
- typedef struct{
- volatile uint16_t ticks;
- volatile float rpm;
- }RPM_t;
- RPM_t RPM;
- int main(void){
- //PortE.0 used to trigger Input Capture
- DDRE |= (1U<<0);
- PORTE &= ~(1U<<0);
- //
- //PortE.1 Input for T4
- DDRE &= ~(1U<<1);
- //
- //OC1A
- DDRB |= (1U<<1);
- //
- //Debugging
- PORTC &= ~(1U<<5);
- DDRC |= (1U<<5);
- //
- //Initiate ADC, PWM1, Timer3CTC, UART
- initADC(ch0, internalVoltage, false, ADC_autoTrigger_en, ADC_timer1OVR_trigger); //This uses timer1 over flow to trigger a conversion of the ADC
- initTimer1PWM();
- initTimer3Delay_100ms(); //100ms
- initUART(async, noParity, oneStop, chSize8); //8-N-1
- sei();
- //
- //Start PWM1
- startPWM1();
- dataString = "Connected";
- sendString_UART();
- while(1){
- //Return RPM value
- RPM.rpm = calculateRPM_x1();
- //Send RPM x1 encoding value
- dataString = "RPM x1: ";
- sendString_UART();
- convert_float_to_string(RPM.rpm);
- sendString_UART();
- //
- //_delay_ms(500);
- }
- }
- void initADC(uint8_t adcCh, uint8_t adcRef, uint8_t leftShift, uint8_t autoTriggerEn, uint8_t autoTrigger){
- //Initiates ADC
- ADMUX |= (adcCh << 0) | (leftShift << 5) | (adcRef << 6);
- ADCSRA |= (1U<<ADEN) | (autoTriggerEn << ADATE) | (0x07U<<ADPS0);
- ADCSRB |= (autoTrigger << ADTS0);
- }
- uint16_t readADC(){
- //Reads ADC
- return (ADCL | (ADCH<<8));
- }
- void initTimer3Delay_100ms(){
- //Inititates Timer3CTC as 100ms delay
- TCCR3A = (ICP_WGM_11_10);
- TCCR3B = (ICP_WGM_13_12 << WGM32);
- OCR3A = (6249U); //100ms
- //OCR3A = 62499; //1s
- }
- /*
- float calculateRPM_x2(){
- initINT0();
- ICP_BUSY = true;
- TCNT3 = 0x00;
- TCNT4 = 0x00;
- TCCR4B |= (0x07) | (1U<<6);
- TCCR3B |= (0x04<<0);
- while(ICP_BUSY);
- TCCR4B &= ~(0x07);
- TCCR3B &= ~(0x07);
- return (RPM.ticks * RPM_conversion);
- }
- */
- float calculateRPM_x1(){
- //Calculates RPM
- ICP_BUSY = true; //Signals Input Capture is busy
- TCNT3 = 0x00; //Reset Timer3
- TCNT4 = 0x00; //Reset Counter4
- TIMSK4 |= (1U<<5); //Enable Input Capture Interrupt
- TIMSK3 |= (1U<<1); //Enable Output Compare Interrupt
- TCCR4B |= (0x07) | (1U<<6); //Set counter4 as rising edge
- TCCR3B |= (0x04<<0); //Set timer3 scaler
- PORTC |= (1U<<5);
- while(ICP_BUSY); //While 100 ms happens, let counter4 count the poles of the encoder
- PORTC &= ~(1U<<5);
- PORTE &= ~(1U<<0); //Reset Software Interrupt
- TCCR3B &= ~(0x07); //Clear clock
- TCCR4B &= ~(0x07); //Clear clock
- return RPM.ticks * RPM_conversion; //Resturn RPM value
- }
- void initINT0(){
- PIND &= ~(1U<<2);
- EICRA = (3U<<0);
- EIMSK = (1<<0);
- }
- void dsINT0(){
- EICRA = 0x00;
- EIMSK = 0x00;
- }
- void initTimer1PWM(unsigned int top){
- //Initiates PWM1
- TCCR1A |= (PWM_nonInvert << COM1A0);
- TCCR1A |= (PWM_WGM_11_10 << WGM10);
- TCCR1B |= (PWM_WGM_13_12 << WGM12);
- }
- void startPWM1(){
- //Starts PWM1
- TCNT1 = 0x00;
- TIMSK1 |= (PWM_timerOVR << TOIE1);
- TCCR1B |= (PWM_8Scalar << CS10);
- }
- void convert_float_to_string(float floatNum){
- //Converts float to string and stores into dataString
- snprintf(charConversion, sizeof(charConversion), "%f\r\n", floatNum);
- dataString = charConversion;
- }
- void sendString_UART(){
- //USART is now busy, and enable TX and interrupts
- //Waits till usart sends to continue
- uart_BUSY = true;
- UCSR0B |= ((txIEN << TXCIE0) |
- (drIEN << UDRIE0) |
- (txEN << TXEN0));
- while(uart_BUSY);
- }
- void initUART(uint8_t umsel, uint8_t upm, uint8_t usbs, uint8_t ucsz){
- //Initiates UART Baud and sets it to a 8-N-1 setting
- UBRR0H = (uint8_t)(0x00);
- UBRR0L = (uint8_t)(BAUDPRESCALAR);
- UCSR0C = (umsel << UMSEL00) |
- (upm << UPM00) |
- (usbs << USBS0) |
- (ucsz << UCSZ00);
- }
- ISR(INT0_vect){
- TCCR4B ^= (0x01);
- }
- ISR(TIMER4_CAPT_vect){
- //Timer4 Capture interrupt
- TIMSK4 &= ~(1U<<5);
- RPM.ticks = (float)((uint16_t)ICR4);
- ICP_BUSY = false;
- }
- ISR(TIMER3_COMPA_vect){
- //Timer3 Compare Interrupt
- PORTE |= (1U<<0); //Sets Timer4 Capture Interrupt
- TIMSK3 &= ~(1U<<1);
- }
- ISR(TIMER1_OVF_vect){
- //Enable ADC interrupt
- ADCSRA |= (1U<<ADIE);
- }
- ISR(ADC_vect){
- //Disable ADC interrupt
- ADCSRA &= ~(1U<<ADIE);
- OCR1A = readADC();
- }
- ISR(USART0_UDRE_vect){
- //If datastring is not empty send character
- //Else send disable interrupt and signal when usart is done
- if(*dataString != '\0'){
- UDR0 = *dataString;
- dataString++;
- }
- else{
- UCSR0B &= ~(drIEN << UDRIE0);
- uart_BUSY = false;
- }
- }
- ISR(USART0_TX_vect){
- //Disables TX and intterupt for power consumption
- UCSR0B &= ~((txIEN << TXCIE0) |
- (txEN << TXEN0));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement