Advertisement
Guest User

SD_main.c

a guest
Nov 5th, 2010
406
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.39 KB | None | 0 0
  1. //**********************************************************
  2. // **** MAIN routine FOR Interfacing microSD/SD CARD ******
  3. //**********************************************************
  4. //Controller: ATmega168 (Clock: 8 Mhz-internal)
  5. //Compiler: AVR-GCC
  6. //Version : 2.1
  7. //Author: CC Dharmani, Chennai (India)
  8. // www.dharmanitech.com
  9.  
  10. //Date: 26 Feb 2009
  11. //********************************************************
  12.  
  13. //Link to the Post: http://www.dharmanitech.com/2009/01/sd-card-interfacing-with-atmega8-fat32.html
  14.  
  15.  
  16. #define F_CPU 8000000UL       //freq 8 MHz
  17. #include <avr/io.h>
  18. #include <avr/pgmspace.h>
  19. #include <avr/interrupt.h>
  20. #include <util/delay.h>
  21. #include <stdlib.h>
  22. #include "SPI_routines.h"
  23. #include "SD_routines.h"
  24. #include "UART_routines.h"
  25. #include "FAT32.h"
  26.  
  27. volatile unsigned long startBlock;
  28. volatile unsigned long totalBlocks;
  29. volatile unsigned char buffer[512];
  30. volatile unsigned long firstDataSector, rootCluster, totalClusters;
  31. volatile unsigned int  bytesPerSector, sectorPerCluster, reservedSectorCount;
  32. volatile uint16_t digitala = 0, digitalb = 0;
  33. volatile int seconds = 0, minutes = 1, hours = 2;
  34. volatile int days = 3, months = 4, years = 10;
  35. volatile int sample = 1;
  36.  
  37.  
  38. void port_init(void)
  39. {
  40. MCUCR = 0x00; // Don't disable pullup resistors
  41.  
  42. // Setup Port B                  DDR PORTB
  43. //   7 - XTAL2                    0   0 (Cannot be used as IO pin)
  44. //   6 - XTAL1                    1   1 (Cannot be used as IO pin)
  45. //   5 - SCK  (DAPA)              1   1
  46. //   4 - MISO (DAPA)              1   1
  47. //   3 - MOSI (DAPA)              1   1
  48. //   2 - SS                       1   1
  49. //   1 - (DAPA)                   1   1
  50. //   0 - Bootloader, Input        1   1 (Pullup Resistor)
  51. //
  52. PORTB = 0xEF; // The description doesnt agree with the settings
  53. DDRB  = 0xEF; // MISO line i/p, rest o/p
  54.  
  55. // Setup Port C                  DDR PORTC
  56. //   6 - Reset, input             0    0
  57. //   5 - LED, logging, ouput      1    0 (LED Off)
  58. //   4 - ANALOG4 (unused), input  0    0
  59. //   3 - ANALOG3, input           0    0
  60. //   2 - ANALOG2, input           0    0
  61. //   1 - ANALOG1, input           0    0
  62. //   0 - Log Button, input        0    1 (Pullup Resistor)
  63. //
  64. DDRC  = 0b00100000;
  65. PORTC = 0b00000001;
  66.  
  67. // Setup Port D                  DDR PORTD
  68. //   7 - Button, timeset, input   0    1 (Pullup Resistor)
  69. //   6 - LED, timeset1, output    1    0 (LED off)
  70. //   5 - LED, timeset2, output    1    0 (LED off)
  71. //   4 -                          1    0
  72. //   3 - INT1, input              0    1 (Pullup Resistor)
  73. //   2 - INT0, input              0    1 (Pullup Resistor)
  74. //   1 - UART TXD, output         1    0
  75. //   0 - UART RXD, input          0    1
  76. //
  77. DDRD  = 0b01110010;
  78. PORTD = 0b10001101;
  79. }
  80.  
  81. //UART0 initialize
  82. // desired baud rate: 19200
  83. // actual: baud rate: 19231 (0.2%)
  84. // char size: 8 bit
  85. // parity: Disabled
  86. void uart0_init(void)
  87. {
  88.  UCSR0B = 0x00; //disable while setting baud rate
  89.  UCSR0A = 0x00;
  90.  UCSR0C = 0x06;
  91.  UBRR0L = 0x19; //set baud rate lo
  92.  UBRR0H = 0x00; //set baud rate hi
  93.  UCSR0B = 0x18;
  94. }
  95.  
  96. // Initialise ADC
  97. void adc_init() {
  98.   // Initialise analog to digital converter
  99.   ADMUX = 0x00; // Set for external reference (3.3V), single ended input
  100.  
  101.   // set analog to digital converter
  102.   // to be enabled, with a clock prescale of 1/128
  103.   // so that the ADC clock runs at 62.5kHz
  104.   ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
  105.  
  106.   // fire a convertsion just to get the ADC warmed up
  107.   ADCSRA |= (1<<ADSC);
  108. }
  109.  
  110. //call this routine to initialize all peripherals
  111. void init_devices(void)
  112. {
  113.  cli();
  114.  port_init();
  115.  spi_init();
  116.  uart0_init();
  117.  adc_init();
  118.  
  119. // Set up debounce timer (Timer0)
  120.  TCCR0A = 0x00;       // Set Timer0 to normal running mode
  121.  TCCR0B = 0x00;       // Ensure Timer0 is stopped
  122.  TCNT0 = 0x00;        // Clear Timer0 counter
  123.  TIMSK0 = 0b00000001; // Enable overflow interrupt on Timer0
  124.  
  125. // Set up Real Time Clock (RTC) timer (16 bit)
  126.  TCCR1A = 0x00;       // Set Timer1 to normal running mode
  127.  TCCR1B = 0x00;       // Ensure Timer1 is stopped
  128.  TCNT1 = 0x85EE;      // Allow 31250 increments per overflow interrupt (1 second)
  129.  TIMSK1 = 0b00000001; // Enable overflow interrupt on Timer1
  130.  TCCR1B = 0b00000100; // Set timer1 running at clk/256
  131.  
  132. // Set up debounce timer (Timer2)
  133.  TCCR2A = 0x00;       // Set Timer2 to normal running mode
  134.  TCCR2B = 0x00;       // Ensure Timer2 is stopped
  135.  TCNT2 = 0x00;        // Clear Timer2 counter
  136.  TIMSK2 = 0b00000001; // Enable overflow interrupt on Timer2
  137.  
  138. // Set up interrupts for digital pulse (INT0 & INT1)
  139. // DDRD = 0b11110111;     // Set PD3(INT1) to input
  140. // PORTD = 0b00001000;    // Set PD3 pullup resistor
  141.  EIMSK = 0b00000011;    // Enable INT1 & INT0
  142.  EICRA = 0b00001010;    // Activate on falling egde (ISK11=1, ISK10=0, ISK01=1, ISK00=0)
  143.  
  144.  sei();                 // Set interrupt enable
  145. }
  146.  
  147.  
  148. int main(void)
  149. {
  150. unsigned char error, FAT32_active, logs;
  151. unsigned int i;
  152. unsigned char fileName[13], fileNameTemp[13];
  153.  
  154. _delay_ms(100);  //delay for VCC stabilization
  155.  
  156. init_devices();
  157.  
  158. TX_NEWLINE;
  159. TX_NEWLINE;
  160. transmitString_F (PSTR("***********************************"));
  161. TX_NEWLINE;
  162. transmitString_F (PSTR("** Mujda Data Logger Development **"));
  163. TX_NEWLINE;
  164. transmitString_F (PSTR("**  Create Consecutive Log File  **"));
  165. TX_NEWLINE;
  166.  
  167. SD_init();
  168. SPI_HIGH_SPEED;   //SCK - 4 MHz
  169.  
  170. _delay_ms(1);
  171.  
  172. // Set the 6 pins to input mode - Two 3 bit numbers  
  173. //DDRC &= ~(1<<PC0); // set PC0 as input
  174. // turn on the internal resistors for the pins
  175. //PORTC |= (1<<PC0); // turn on internal pull up resistor for PA0
  176.  
  177. FAT32_active = 1;
  178. logs = 0;
  179.  
  180. error = getBootSectorData (); //read boot sector and keep necessary data in global variables
  181. if(error)  
  182. {
  183.   transmitString_F (PSTR("FAT32 not found!"));  //FAT32 incompatible drive
  184.   while(1){
  185.     PORTC |= 0b00100000; // Turn on LED1
  186.     _delay_ms(500);
  187.     PORTC &= 0b11011111; // Turn off LED1
  188.     _delay_ms(500);
  189.     }
  190.   FAT32_active = 0;
  191. }
  192.  
  193.  
  194.  
  195. while(FAT32_active == 1)
  196. {
  197.     PORTC |= 0b00100000; // Turn on LED1   
  198.                          // Pause for 2 seconds before checking for button press as button may have just been pressed to stop logging
  199.     _delay_ms(2000);
  200.     transmitString_F (PSTR("Press button to start logging"));
  201.     TX_NEWLINE;
  202.     while((PINC & 1) == 1);
  203.     PORTC &= 0b11011111; // Turn off LED1  
  204.    
  205.     fileName[0] = 'D';
  206.     fileName[1] = 'a';
  207.     fileName[2] = 't';
  208.     fileName[3] = 'a';
  209.     fileName[4] = '0';
  210.     fileName[5] = '0';
  211.     fileName[6] = '.';
  212.     fileName[7] = 'c';
  213.     fileName[8] = 's';
  214.     fileName[9] = 'v';
  215.     fileName[10] = 0x00;
  216.     fileName[11] = 0x00;
  217.     fileName[12] = 0x00;
  218.     for(i=0; i<13; i++) fileNameTemp[i] = fileName[i];   //transfer to temporary variable due to Verification process
  219.     while(readFile (VERIFY, fileNameTemp) == 1){
  220.         fileName[5]++;
  221.         if(fileName[5] == ':'){fileName[5] = '0'; fileName[4]++;}
  222.         if(fileName[4] == ':'){transmitString_F(PSTR("Too many log files: ")); logs = 1;}
  223.         for(i=0; i<13; i++) fileNameTemp[i] = fileName[i];
  224.     }
  225.     if(logs == 0) createFile(fileName);
  226. }
  227.  
  228. return 0;
  229. }
  230.  
  231. // Interrupt Service Routine
  232. // Call:
  233. //   On -ve edge of INT1
  234. // Action:
  235. //   If last call was greater than 1.024mS before, then:
  236. //      - Pulse counter incremented
  237. //      - Set timer counter going
  238. //
  239. ISR(SIG_INTERRUPT1)
  240. {
  241.   if(TCNT0 == 0){         // If Timer0 is not running (enough time to exclude switch bounce)
  242.      digitalb++;          // Increment counts per sample
  243.      TCNT0 = 0xF8;        // Set counter to 8 increments before overflow
  244.      TCCR0B = 0b00000101; // Set Timer0 Prescaler to 1024
  245.   }                       // 8MHz/1024 = 7812.5 or 0.128mS per increment
  246. }                         // 8 increments (0xF8 to 0x00) = 1.024mS to Timer0 reset
  247.  
  248. // Interrupt Service Routine
  249. // Call:
  250. //   On -ve edge of INT0
  251. // Action:
  252. //   If last call was greater than 1.024mS before, then:
  253. //      - Pulse counter incremented
  254. //      - Set timer counter going
  255. //
  256. ISR(SIG_INTERRUPT0)
  257. {
  258.   if(TCNT2 == 0){         // If Timer2 is not running (enough time to exclude switch bounce)
  259.      digitala++;          // Increment counts per sample
  260.      TCNT2 = 0xF8;        // Set counter to 8 increments before overflow
  261.      TCCR2B = 0b00000101; // Set Timer0 Prescaler to 1024
  262.   }                       // 8MHz/1024 = 7812.5 or 0.128mS per increment
  263. }                         // 8 increments (0xF8 to 0x00) = 1.024mS to Timer2 reset
  264.  
  265. // Interrupt Service Routine
  266. // Call:
  267. //   On Timer0 overflow
  268. // Action:
  269. //   - Stop Timer0
  270. //   - Ensure Timer0 counter is zeroed
  271. //
  272. ISR(TIMER0_OVF_vect)
  273. {
  274. TCCR0B = 0b00000000;    // Stop Timer0
  275. TCNT0 = 0;              // Ensure counter is zeroed
  276. }
  277.  
  278. // Interrupt Service Routine
  279. // Call:
  280. //   On Timer1 overflow
  281. // Action:
  282. //   - Set timer1 0x85EE (1 second to next interrupt)
  283. //   - Update RTC
  284. //   - Set the sample flag at appropriate interval
  285. //
  286. ISR(TIMER1_OVF_vect)
  287. {
  288. TCNT1 = 0x85EE;      // Allow 31250 increments per overflow interrupt (1 second)
  289. seconds++;
  290.  
  291. sample = 1;     // Set the sample flag to initiate sampling
  292.  
  293. if(seconds == 60){
  294.   seconds = 0;
  295.   minutes++;
  296.   }
  297. if(minutes == 60){
  298.   minutes = 0;
  299.   hours++;
  300.   }
  301. if(hours == 24){
  302.   hours = 0;
  303.   days++;
  304.   }
  305. if(days == 29 && months == 2){
  306.   days = 1;
  307.   months++;
  308.   }
  309. if(days == 31 && ((months == 4) || (months == 6) || (months == 9) || (months == 11))){
  310.   days = 1;
  311.   months++;
  312.   }
  313. if(days == 32){
  314.   days = 1;
  315.   months++;
  316.   }
  317. if(months == 13){
  318.   months = 1;
  319.   years++;
  320.   }
  321. }
  322.  
  323. // Interrupt Service Routine
  324. // Call:
  325. //   On Timer2 overflow
  326. // Action:
  327. //   - Stop Timer2
  328. //   - Ensure Timer2 counter is zeroed
  329. //
  330. ISR(TIMER2_OVF_vect)
  331. {
  332. TCCR2B = 0b00000000;    // Stop Timer0
  333. TCNT2 = 0;              // Ensure counter is zeroed
  334. }
  335. //********** END *********** www.dharmanitech.com *************
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement