Advertisement
Guest User

Untitled

a guest
Apr 8th, 2020
245
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.17 KB | None | 0 0
  1. #define F_CPU 16000000
  2. #include <avr/io.h>
  3. #include <avr/interrupt.h>
  4. #include <stdio.h>
  5. #include <avr/delay.h>
  6.  
  7. #define ch0 0x00
  8. #define internalVoltage 0x03
  9.  
  10. #define PWM_8Scalar             0x02
  11. #define PWM_noScalar            0x01
  12. #define PWM_WGM_11_10           0x03
  13. #define PWM_WGM_13_12           0x00
  14. #define ICP_WGM_11_10           0x00
  15. #define ICP_WGM_13_12           0x01
  16. #define ICP_Toggle              0x01
  17. #define ICP_OC_High             0x03
  18. #define PWM_nonInvert           0x02
  19. #define PWM_timerOVR            0x01
  20. #define ADC_timer1OVR_trigger   0x06
  21. #define ADC_autoTrigger_en      en
  22.  
  23. #define rxEN 1
  24. #define txIEN 1
  25. #define drIEN 1
  26. #define txEN 1
  27. #define eightBit 0x03
  28. #define async 0x00
  29. #define sync 0x01
  30. #define noParity 0x00
  31. #define oneStop 0x00
  32. #define twoStop 0x01
  33. #define chSize8 0x03
  34. #define BAUD 9600
  35. #define BAUDPRESCALAR ((F_CPU/(BAUD))/16 - 1) //Register Values
  36.  
  37. #define RPM_conversion          ((float)(60)/(192))
  38.  
  39. #define ICES                    (1U)
  40.  
  41. #define true                    0x01U
  42. #define false                   0x00U
  43. #define bool                    unsigned int
  44. #define en                      0x01
  45.  
  46.  
  47. uint16_t readADC();
  48. void adcStartConvertion();
  49. void initADC(uint8_t adcCh, uint8_t adcRef, uint8_t leftShift, uint8_t autoTriggerEn, uint8_t autoTrigger);
  50. void initTimer1PWM();
  51. void initTimer3Delay_100ms();
  52. void initINT0();
  53. void initUART(uint8_t umsel, uint8_t upm, uint8_t usbs, uint8_t ucsz);
  54. float calculateRPM_x1();
  55. float calculateRPM_x2();
  56. void convert_float_to_string(float floatNum);
  57. void sendString_UART();
  58. void startPWM1();
  59. void stopPWM1();
  60. void dsINT0();
  61.  
  62. volatile bool   ICP_BUSY;
  63. volatile unsigned int adcBUSY;
  64. static volatile char* dataString;
  65. static char charConversion[20];
  66. volatile bool uart_BUSY;
  67. typedef struct{
  68.     volatile uint16_t ticks;
  69.     volatile float rpm;
  70. }RPM_t;
  71.  
  72. RPM_t RPM;
  73. int main(void){
  74.    
  75.     //PortE.0 used to trigger Input Capture
  76.     DDRE |= (1U<<0);
  77.     PORTE &= ~(1U<<0);
  78.     //
  79.    
  80.     //PortE.1 Input for T4
  81.     DDRE &= ~(1U<<1);  
  82.     //
  83.    
  84.     //OC1A
  85.     DDRB |= (1U<<1);
  86.     //
  87.    
  88.     //Debugging
  89.     PORTC &= ~(1U<<5);
  90.     DDRC |= (1U<<5);
  91.     //
  92.    
  93.     //Initiate ADC, PWM1, Timer3CTC, UART
  94.     initADC(ch0, internalVoltage, false, ADC_autoTrigger_en, ADC_timer1OVR_trigger); //This uses timer1 over flow to trigger a conversion of the ADC
  95.     initTimer1PWM();
  96.     initTimer3Delay_100ms(); //100ms
  97.     initUART(async, noParity, oneStop, chSize8); //8-N-1
  98.     sei();
  99.     //
  100.    
  101.     //Start PWM1
  102.     startPWM1();
  103.    
  104.     dataString = "Connected";
  105.     sendString_UART();
  106.  
  107.     while(1){  
  108.  
  109.     //Return RPM value
  110.     RPM.rpm = calculateRPM_x1();
  111.    
  112.     //Send RPM x1 encoding value
  113.     dataString = "RPM x1: ";
  114.     sendString_UART();
  115.     convert_float_to_string(RPM.rpm);
  116.     sendString_UART();
  117.     //
  118.    
  119.     //_delay_ms(500);
  120.     }
  121. }
  122.  
  123.  
  124. void initADC(uint8_t adcCh, uint8_t adcRef, uint8_t leftShift, uint8_t autoTriggerEn, uint8_t autoTrigger){
  125. //Initiates ADC
  126.     ADMUX  |= (adcCh << 0) | (leftShift << 5) | (adcRef << 6);
  127.     ADCSRA |= (1U<<ADEN) | (autoTriggerEn << ADATE) | (0x07U<<ADPS0);
  128.     ADCSRB |= (autoTrigger << ADTS0);
  129. }
  130.  
  131. uint16_t readADC(){
  132. //Reads ADC
  133.     return (ADCL | (ADCH<<8));
  134. }
  135.  
  136. void initTimer3Delay_100ms(){
  137. //Inititates Timer3CTC as 100ms delay
  138.     TCCR3A = (ICP_WGM_11_10);
  139.     TCCR3B = (ICP_WGM_13_12 << WGM32);
  140.     OCR3A  = (6249U); //100ms
  141.     //OCR3A = 62499; //1s
  142. }
  143. /*
  144. float calculateRPM_x2(){
  145.    
  146.     initINT0();
  147.     ICP_BUSY = true;
  148.     TCNT3 = 0x00;
  149.     TCNT4 = 0x00;
  150.     TCCR4B |= (0x07) | (1U<<6);
  151.     TCCR3B |= (0x04<<0);
  152.  
  153.     while(ICP_BUSY);
  154.    
  155.     TCCR4B &= ~(0x07);
  156.     TCCR3B &= ~(0x07);
  157.    
  158.     return (RPM.ticks * RPM_conversion);   
  159. }
  160. */
  161.  
  162. float calculateRPM_x1(){
  163. //Calculates RPM
  164.        
  165.     ICP_BUSY = true; //Signals Input Capture is busy
  166.     TCNT3 = 0x00;   //Reset Timer3
  167.     TCNT4 = 0x00;   //Reset Counter4
  168.     TIMSK4 |= (1U<<5); //Enable Input Capture Interrupt
  169.     TIMSK3 |= (1U<<1); //Enable Output Compare Interrupt
  170.     TCCR4B |= (0x07) | (1U<<6); //Set counter4 as rising edge
  171.     TCCR3B |= (0x04<<0); //Set timer3 scaler
  172.     PORTC |= (1U<<5);
  173.     while(ICP_BUSY); //While 100 ms happens, let counter4 count the poles of the encoder
  174.     PORTC &= ~(1U<<5);
  175.     PORTE &= ~(1U<<0); //Reset Software Interrupt
  176.    
  177.     TCCR3B &= ~(0x07); //Clear clock
  178.     TCCR4B &= ~(0x07); //Clear clock
  179.    
  180.     return RPM.ticks * RPM_conversion; //Resturn RPM value
  181. }
  182.  
  183. void initINT0(){
  184.     PIND &= ~(1U<<2);
  185.     EICRA  = (3U<<0);
  186.     EIMSK  = (1<<0);
  187. }
  188.  
  189. void dsINT0(){
  190.     EICRA = 0x00;
  191.     EIMSK = 0x00;
  192. }
  193.  
  194. void initTimer1PWM(unsigned int top){
  195. //Initiates PWM1
  196.     TCCR1A |= (PWM_nonInvert << COM1A0);
  197.     TCCR1A |= (PWM_WGM_11_10 << WGM10);
  198.     TCCR1B |= (PWM_WGM_13_12 << WGM12);
  199. }
  200.  
  201. void startPWM1(){
  202. //Starts PWM1
  203.     TCNT1 = 0x00;
  204.     TIMSK1 |= (PWM_timerOVR << TOIE1);
  205.     TCCR1B |= (PWM_8Scalar  << CS10);
  206. }
  207.  
  208. void convert_float_to_string(float floatNum){
  209. //Converts float to string and stores into dataString
  210.     snprintf(charConversion, sizeof(charConversion), "%f\r\n", floatNum);
  211.     dataString = charConversion;
  212. }
  213.  
  214. void sendString_UART(){
  215. //USART is now busy, and enable TX and interrupts
  216. //Waits till usart sends to continue
  217.     uart_BUSY = true;
  218.     UCSR0B |= ((txIEN << TXCIE0) |
  219.                (drIEN << UDRIE0) |
  220.                (txEN  << TXEN0));
  221.  
  222.     while(uart_BUSY);
  223. }
  224.  
  225.  
  226. void initUART(uint8_t umsel, uint8_t upm, uint8_t usbs, uint8_t ucsz){
  227. //Initiates UART Baud and sets it to a 8-N-1 setting
  228.     UBRR0H = (uint8_t)(0x00);
  229.     UBRR0L = (uint8_t)(BAUDPRESCALAR);
  230.    
  231.     UCSR0C = (umsel << UMSEL00) |
  232.              (upm   << UPM00)   |
  233.              (usbs  << USBS0)   |
  234.              (ucsz  << UCSZ00);
  235. }
  236.  
  237. ISR(INT0_vect){
  238.     TCCR4B ^= (0x01);
  239. }
  240.  
  241. ISR(TIMER4_CAPT_vect){
  242. //Timer4 Capture interrupt
  243.     TIMSK4 &= ~(1U<<5);
  244.     RPM.ticks = (float)((uint16_t)ICR4);
  245.     ICP_BUSY = false;
  246. }
  247.  
  248. ISR(TIMER3_COMPA_vect){
  249. //Timer3 Compare Interrupt
  250.     PORTE |= (1U<<0); //Sets Timer4 Capture Interrupt
  251.     TIMSK3 &= ~(1U<<1);
  252. }
  253.  
  254. ISR(TIMER1_OVF_vect){
  255. //Enable ADC interrupt
  256.     ADCSRA |= (1U<<ADIE);
  257. }
  258.  
  259. ISR(ADC_vect){
  260. //Disable ADC interrupt
  261.     ADCSRA &= ~(1U<<ADIE);
  262.     OCR1A = readADC();
  263. }
  264.  
  265. ISR(USART0_UDRE_vect){
  266. //If datastring is not empty send character
  267. //Else send disable interrupt and signal when usart is done
  268.     if(*dataString != '\0'){
  269.         UDR0 = *dataString;
  270.         dataString++;
  271.     }
  272.     else{
  273.         UCSR0B &= ~(drIEN << UDRIE0);
  274.         uart_BUSY = false;
  275.     }
  276. }
  277.  
  278. ISR(USART0_TX_vect){
  279. //Disables TX and intterupt for power consumption
  280.     UCSR0B &= ~((txIEN << TXCIE0) |
  281.                 (txEN  << TXEN0));
  282. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement