ECE 4510/5530 Microcontroller Applications Week 5 Lab 4& Lab 5 Dr. Bradley J. Bazuin Associate Professor Department of Electrical and Computer Engineering College of Engineering and Applied Sciences
Lab 4 & 5 Element • Hardware Development – Three terminal linear regulator – Enhanced Capture Timer (ECT) (Chap. 8) • • •
Modulus Down-Counter (time delay, periodicity) Output Compare (periodic output signals, periodicity) Input Capture (external event timing)
– Serial Communication Interface (SCI) (Chap. 9) – Relay Driver – IRQn Interrupt (Chap. 6)
• Software Development – Polling vs. Interrupts – Time of Day (register limitations) – Text buffers ECE 2510
2
MAKING SOUND
ECE 4510/5530
3
Chapter 8 Example Making Sound • A sound can be generated by creating a digital waveform with appropriate frequency and using it to drive a speaker or a buzzer. • The simplest song is a two-tone siren.
HCS12DP256 3.3 F PT5
Buzzer
Figure 8.21 Circuit connection for a buzzer
ECE 4510/5530
4
Example 8.7: Algorithm for Generating a Siren •
Step 1 – Enable an output compare channel to drive the buzzer (or speaker).
•
Step 2 – Start an output compare operation with a delay count equal to half the period of the siren and enable the OC interrupt.
•
Step 3 – Wait for the duration of the siren tone (say half a second). During the waiting period, interrupts will be requested many times by the output compare function. The interrupt service routine simply restart the output compare operation.
•
Step 4 – At the end of the siren tone duration, choose a different delay count for the output compare operation so that the siren sound may have a different frequency.
•
Step 5 – Wait for the same duration as in Step 3. During this period, many interrupts will be requested by the output compare operation.
•
Step 6
– ECE 4510/5530
Go to Step 2.
5
Example 8.7 Siren Generation • Write a program to generate a two-tone siren that oscillates between 300 Hz and 1200 Hz. • Solution: – Set the prescaler to TCNT to 1:8. – The delay count for the low frequency tone is (24000000 8) 300 2 = 5000. – The delay count for the high frequency tone is (24000000 8) 1200 2 = 1250.
ECE 4510/5530
6
C Program for Siren Generation (1 of 2) #include #include #define #define int
delay;
"c:\egnu091\include\hcs12.h" "c:\egnu091\include\delay.c" HiFreq 1250 LoFreq 5000 /* delay count for OC5 operation */
int main(void) { asm("cli"); TSCR1 = 0x90; /* enable TCNT and fast timer flag clear */ TSCR2 = 0x03; /* set prescaler to TCNT to 1:8 */ TIOS |= BIT5; /* enable OC5 */ TCTL1 = 0x04; /* select toggle for OC5 pin action */ delay = HiFreq; /* use high frequency delay count first */ TC5 = TCNT + delay; /* start an OC5 operation */ TIE |= BIT5; /* enable TC5 interrupt */ asm("cli"); ECE 4510/5530
7
C Program for Siren Generation (2 of 2) while(1) { delayby100ms(5); delay = LoFreq; delayby100ms(5); delay = HiFreq; } return 0;
/* wait for half a second */ /* switch to low frequency tone */ /* wait for half a second */ /* switch to high frequency tone */
}
#pragma interrupt_handler oc5_ISR void oc5_ISR(void) { TC5 += delay; } #pragma abs_address:vtimch5 // Initialize the Interrupt Vector address void (*interrupt_vectors[]) (void) = {oc5_ISR}; // Assign the function pointer #pragma end_abs_address // to the ISR ECE 4510/5530
8
Preferred Initialization void init_TimerCh5(void) { TSCR1 = 0x90; TSCR2 = 0x03; TIOS |= BIT5; TCTL1 = 0x04; TIE |= BIT5; }
/* enable TCNT and fast timer flag clear */ /* set prescaler to TCNT to 1:8 */ /* enable OC5 */ /* select toggle for OC5 pin action */ /* enable TC5 interrupt */
Then we have …. int main(void) { asm(“sei"); init_TimerCh5(); delay = HiFreq; TC5 = TCNT + delay; asm("cli"); ECE 4510/5530
/* initialize channel 5*/ /* use high frequency delay count first */ /* start an OC5 operation */
9
A Better Way – Audio Amp
ECE 4510/5530
10
LM386 • Input gain control using potentiometer • Device Gain control 20-200 with feedback RC • Drives an 8 ohm speaker
$0.93 ea. at Digikey ECE 4510/5530
11
Speaker
$1.10 ea. at Digikey
ECE 4510/5530
12
You may want to filter
http://homepages.wmich.edu/~bazuinb/FiltersManual_RevD.pdf
ECE 4510/5530
13
Multiple stages are needed for a good filter Ask Dr. Bazuin for filter design notes if you need them …
ECE 4510/5530
Audio amplifier to drive the speaker
14
TEXT PROCESSING
ECE 4510/5530
15
The SCI0 Port to the PC • Built in functions to make it connect with the PC – All you need is code …
• Standard PC to modem cable – Not a null modem cable
• Textbook DVD – And on-line material provided by Dr. Bazuin
ECE 4510/5530
16
The HCS12 SCI Subsystem Registers Outlined in red
SCI data register Receive shift register
RxD
Interrupt generation
Idle IRQ RDRF/OR IRQ
Bus clock
BAUD generator
Receive and wake up control
16
O R I N G
Data format control
IRQ to CPU
Transmit control Transmit shift register
Interrupt generation
TDRE IRQ
Status Register 1
TC IRQ
Status Register 2
SCI data register TxD Figure 9.8 HCS12 SCI block diagram
ECE 4510/5530
17
SCI0 Initialization void init_sci0(void) { // BR=ECLK/(16 x BR) SCI0BD = 156; SCI0CR1 = SCISWAI | WAKE | ILT ; SCI0CR1 &= ~(M | PE | PT) ; SCI0CR2 = TE | RE;
// 24 MHz E-clock, 9600 bps desired (0.16% error) //SCISWAI, wakeup to mark, idle line after stop // 8-bit data, parity disabled, even parity // transmitter enable, receiver enable, // no interrupts enabled, not a break bit, not wake up
}
ECE 4510/5530
18
Baud Rate Generation (1 of 2) • The HCS12 SCI module uses a 13-bit counter to generate this clock signal. • The baud rate generator divides down the E clock to derive the clock signal for reception and transmission. • The user writes an appropriate value into the SCIxBDH and SCIxBDL (x = 0 or 1) register pair to set the baud rate.
reset:
7
6
5
4
3
2
1
0
0
0
0
SBR12
SBR11
SBR10
SBR9
SBR8
0
0
0
0
0
0
0
0
(a) SCI baud rate control register high (SC0BDH/SC1BDH)
reset:
7
6
5
4
3
2
1
0
SBR7
SBR6
SBR5
SBR4
SBR3
SBR2
SBR1
SBR0
0
0
0
0
0
1
0
0
(b) SCI baud rate control register low (SC0BDL/SC1BDL)
ECE 4510/5530
Figure 9.9 SCI baud rate control register
19
The SCI Control Registers (1 of 2) 7
6
LOOPS SCISWAI
reset:
ECE 4510/5530
0
0
5
4
3
2
1
0
RSRC
M
WAKE
ILT
PE
PT
0
0
0
0
0
0
LOOPS: Loop select bit 0 = loop operation disabled 1 = loop operation enabled SCISWAI: SCI stop in wait mode 0 = SCI enabled in wait mode. 1 = SCI disabled in wait mode. RSRC: Receiver source bit When LOOPS = 1, the RSRC bit determines the source for the receiver shift register 0 = receiver input connected to the transmitter internally (not TxD pin). 1 = receiver input connected extrenally to the transmitted (TxD pin) M: Data format mode bit 0 = one start bit, eight data bits, one stop bit 1 = one start bit, nine data bits, one stop bit WAKE: Wakeup condition bit 0 = idle line wakeup 1 = address mark wakeup (last data bit set) ILT: Idle line type bit 0 = idle character bit count begins after start bit 1 = idle character bit count begins after the stop bit PE: parity enable bit 0 = parity disabled 1 = parity enabled PT -- parity type bit (for both transmit and receive) 0 = even parity selected 1 = odd parity selected Figure 9.10 SCI controlregister 1 (SC0CR1/SC1CR1)
20
The SCI Control Registers (2 of 2) value after reset
ECE 4510/5530
7
6
5
4
3
2
1
0
TIE
TCIE
RIE
ILIE
TE
RE
RWU
SBK
0
0
0
0
0
0
0
0
TIE: Transmit interrupt enable bit 0 = TDRE interrupt disabled 1 = TDRE interrupt enabled. TCIE: Transmit complete interrupt enable bit 0 = TC interrupt disabled 1 = TC interrupt enabled RIE: Receiver full interrupt enable bit 0 = RDRF and OR interrupts disabled 1 = RDRF and OR interrupt enabled ILIE: Idle line interrupt enable bit 0 = IDLE interrupt disabled 1 = IDLE interrupt enabled TE: Transmitter enable bit 0 = transmitter disabled 1 = transmitter enabled RE: Receiver enable 0 = receiver disabled 1 = receiver enabled RWU: Receiver wakeup bit 0 = normal SCI receiver 1 = enables the wakeup function and inhibits further receiver interrupts. Normally, hardware wakes up the receiver by automatically clearing this bit. SBK: Send break bit 0 = no break characters 1 = generate a break code, at least 10 or 11 contiguous 0s. As long as SBK remains set, the transmitter sends 0s. Figure 9.11 SCI control register 2 (SC0CR2/SC1CR2)
21
Getchar and Putchar /******************************************************************/ /* The following function uses polling method to read a character */ /* from SCI0 port. */ /******************************************************************/ int getchar(void) { while(!(SCI0SR1 & RDRF)); // poll the status bit return SCI0DRL; // read and return the value }
/*****************************************************************/ /* The following function uses the polling method to output a */ /* character to the SCI0 port. */ /*****************************************************************/ int putchar(char cx) { while(!(SCI0SR1 & TDRE)) )); // poll the status bit continue; SCI0DRL = cx; // output the character return 0; } ECE 4510/5530
Get and Put are unique to every microcontroller. (registers and status bits) They are called by C standard I/O routines. See text files “stdio.c” 22 Or better yet stdio_hcs.c from Dr. Bazuin
Output to a new line /*******************************************************************/ /* The following function outputs a carriage return and a linefeed */ /* to move the cursor to the first column of the next row. */ /*******************************************************************/ int newline(void) { putchar(0x0D); // Carriage Return putchar(0x0A); // Line Feed return 0; }
ECE 4510/5530
23
Reading Into a Buffer /******************************************************************/ /* The following function reads a string from the SCI0 port by */ /* calling the getchar function until the CR character is reached */ /******************************************************************/ int getstr(char *ptr) { while (1) { *ptr = getchar(); if (*ptr == 0x0D){ *ptr = 0; return 0; } else ptr++; } return 0; }
ECE 4510/5530
24
Using the stdio library Input-output manipulation functions stdin – makes a function call to getchar stdout – makes a function call to putchar Name getc getchar gets
Notes reads and returns a character from a given stream and advances the file position indicator; it is allowed to be a macro with the same effects as fgetc, except that it may evaluate the stream more than once has the same effects as getc(stdin) reads characters from stdin until a newline is encountered and stores them in its only argument
printf sprintf
used to print to the standard output stream used to print to a char array (C string)
putc putchar puts
writes and returns a character to a stream and advances the file position indicator for it; equivalent to fputc, except that a macro version may evaluate the stream more than once has the same effects as putc(stdout) outputs a character string to stdout
scanf, sscanf,
used to input from the standard input stream used to input from a char array (e.g., a C string)
ECE 4510/5530
25
Character String Buffers • Memory space allocated for ASCII text string data. – Functions can operate on string buffers instead of “standard I/O”
• Separate the operation of string generation or interpretation from string output and input! – Generate to a string buffer with no polling delays! sprintf instead of printf – Read/operate on a received string buffer with no polling delays! sscanf instead of scanf – Change how characters are read and written using SCI0 from polling to interrupts!
ECE 4510/5530
26
Sunseeker Text Strings //public declarations constants static char RS232Cmd[5] = "+++\r\0"; static char RS232_Test1[13] = "Sunseeker \n\r\0"; static char RS232_Test2[9] = "2012. \n\r\0"; static char Parse_header[6][5] = {"LTC \0","ADC \0","ISH \0","ERR \0","BPS \0","BPC \0"}; char test_buffer[60]; char test_buffer_PC[60]; char xmit_buffer[60]; char xmit_buffer_PC[60]; char parse_buff[8];
ECE 4510/5530
27
Sunseeker Put String Interrupt Start void BPS2PC_put_int(void) { extern char *putPC_ptr; extern char put_status_PC; char ch; ch = *putPC_ptr++;
ECE 4510/5530
if (ch == '\0') { UCA3IE &= ~UCTXIE; put_status_PC = FALSE; } else { UCA3TXBUF = ch; UCA3IE |= UCTXIE; put_status_PC = TRUE; } }
28
Sunseeker ISR /* * BPS2PC Interrupt Service Routine */ #pragma vector=USCI_A3_VECTOR __interrupt void USCI_A3_ISR(void) { extern char *putPC_ptr, *getPC_ptr; extern char put_status_PC, get_status_PC, BPS2PC_RX_flag; char ch; switch(__even_in_range(UCA3IV,16)) { case 0: // Vector 0 - no interrupt break; case 2: // Data Received - UCRXIFG ch = UCA3RXBUF; *getPC_ptr++ = ch; if (ch == 0x0D){ *getPC_ptr = 0; getPC_ptr = &test_buffer_PC[0]; BPS2PC_RX_flag = TRUE; get_status_PC = FALSE; } else { get_status_PC = TRUE; } ECE break; 4510/5530
case 4: // TX Buffer Empty - UCTXIFG ch = *putPC_ptr++; if (ch == '\0') { UCA3IE &= ~UCTXIE; put_status_PC = FALSE; } else { UCA3TXBUF = ch; } break; default: break; } }
String Pointers Used. Check for TX string null and RX string .
29
Creating Multi-line Status Output // Handle BPS to BPS communications events if ((textcomm_flag) && (send_text)) { if(put_status == FALSE) { if(ltc_xcnt