JohnLeung
Joined: 18 May 2004 Posts: 15
|
4" 7-segment LED display in 3-digit with 2x7W amplifier |
Posted: Thu Jan 12, 2006 4:42 am |
|
|
Dear Sirs
A highly recommended book for embedded C programmers :
Embedded System Building Blocks, Complete and Ready-to-use Modules in C, by Jean J. Labrosse.
I have modified one of the chapters on 7-segment LED display for CCS PICC. Very good performance result with my module being able to communicate with a PC, with DING DONG alert tone (have built-in 7W amplifier), and multiplex feature for 1-digit to max. 15 digits from a single mcu 16F877 @ 20MHz!
Interested parties can download the whole project under www.TechToys.com.hk
John
Code: |
/***************************************************************************************************
* This is a demonstration for PIC16-LEDSTK1 by TechToys (www.TechToys.com.hk)
*
* Original :
* Used in an automatic queuing system for a spam
* Intended for showing queue number in 6 groups (3-digit per group)
*
* Now :
* Modified for PIC16-LEDSTK1 in 3-digit format
* Interrupt tasks:
a) #INT_TIMER0, for multiplexing the LED display
b) #INT_RDA, for command / data receive
c) #INT_TBE, for command / data ack
*
* DisplayManager() is the only function to decode a string/command from a remote PC and
* ouptut the string to LED display board. DisplayManager() should be inside TMR1 interrupt
* routine because BeepManager() is using a simple delay_us() function,
* which can "jam" the main loop. If DisplayManager() was running in main() loop, a frequent
* data sequence from PC could overflow the UART receive buffer easily.
*
* Packet Protocol:
* +-------+-------+-------+------------+------------+------+
* | '0' | '1' | '2' |reserve byte|reserve byte| 0x0d |
* +-------+-------+-------+------------+------------+------+
* The length of a complete message is dependent on variables DataBuf[6] array
* declared under DisplayManager(void).
* For example, we want to display 3-digit '0' '1' '2' on the LEDs, we need to write
* ASCII characters '0' '1' '2' 'reserve byte' 'reserve byte' 0x0d to PIC16-LEDSTK1
* Reserve byte can be used for future expansion, or checksum, etc.
*
* It is easy to modify DisplayManager(void) for display > 3 digits
* Adjust the TMR0 rate for different brightness or change the R2 resistor value onboard
*
* Hardware : PCB 11OCT2004.001
* Software : main1.c, demonstration program for PIC16-LEDSTK1
* Created by : John Leung (www.TechToys.com.hk)
* Date: 22th Dec 2004 (Version 1.0)
* History : modified for PIC16-LEDSTK1 dated 12 Jan 2006
***************************************************************************************************/
#include <16F877a.h> // register definition file for PIC16F877a
#fuses HS,NOWDT,NOLVP,PUT // a Microchip PIC16F877
#priority rda, timer1, timer0 // define a priority over the interrupt source
#use delay(clock=20000000)
#include "OS_CPU.h" //typedef compatible with uCOS-II, specified to CCS PICC
#include "USART.h" //USART with serial 232 I/O buffer
#include "USART.c"
#include "LED.h" //LED driver header
#include "LED.c" //LED driver
#include "BEEP.c" //For DINGDONG generation via PORTC.2, modified from CCS driver
INT8U BeepCtr=0;
/***********************************************************************************************
***************************** Function Prototypes ****************************
************************************************************************************************/
void DisplayManager(void);
void BeepManager(void);
/***********************************************************************************************
******************** Interrupt handlers *******************************************
************************************************************************************************/
#int_rda
void rda_isr(void) //Receive command from remote console
{
serial_rx_isr();
}
#int_tbe
void tbe_isr(void) //Send Command (optional) to remote console for ack
{
serial_tx_isr();
}
#int_TIMER0
void TIMER0_isr(void)
{
set_timer0(178); //reset for ~2ms overflow with prescaler 128, 20MHz clock
DispMuxHandler();
}
#int_TIMER1
void TIMER1_isr(void)
{
DisplayManager();
}
/***********************************************************************************************
**************************************** MAIN *******************************************
************************************************************************************************/
void main(void)
{
output_low(PIN_B7); //disable power amplifier
set_adc_channel(NO_ANALOGS); //Since PortA & PortE has been used for digit select
enable_interrupts(int_rda); //enable USART RX
DispInit(); //Initialize 7-seg LED
setup_counters(RTCC_INTERNAL, RTCC_DIV_128);//Adjust timer0 for multiplexing the display
enable_interrupts(INT_TIMER0); //Enable tmr0 interrupt
setup_timer_1(T1_INTERNAL|T1_DIV_BY_2); //setup timer1 for character receive and display
enable_interrupts(INT_TIMER1);
enable_interrupts(global);
for(;;) {
BeepManager(); //output DING DONG via TDA8944 ampifier onboard
}
}
/*********************************************************************************************
**************************************** Sub-routine *****************************************
*********************************************************************************************/
void DisplayManager(void)
{
INT8U c;
INT8U s[DISP_N_SS]; //Data received for display, DISP_N_SS=3 for PIC16-LEDSTK1 demo
INT8U crx;
INT8U DataBuf[6]; //data buffer for serial_rx_isr()
if (EndOfMsg_Flg==TRUE) //Some character in RX_Buffer
{
crx = 0;
c = bgetc();
while (c!= EndOfMsg){
DataBuf[crx++] = c;
c = bgetc();
}
EndOfMsg_Flg = FALSE;
s[0]=DataBuf[0];s[1]=DataBuf[1];s[2]=DataBuf[2];
DispStr(0,s); //output to LED display board
BeepCtr++; //output an alert tone "DING DONG"
bputc('*'); //Acknowledge the PC for a successful message
}
}//DisplayManager()
void BeepManager(void)
{
if (BeepCtr>0){ //BeepCtr increment on every valid call
BeepCtr--; //BeepCtr++ in DisplayManager()
output_high(PIN_B7); //ON amplifier
delay_us(500); //For stablize the amplifier
generate_tone(585, 600); //DING
generate_tone(465, 900); //DONG
output_low(PIN_B7); //OFF amplifier
}
}//BeepManager()
|
Code: |
/*
*********************************************************************************************************
*
* Multiplexed LED Display Driver
* Reference: Jean J. Labrosse, Embedded Systems Building Blocks
*
* Filename : LED.h
* Programmer : John Leung (www.TechToys.com.hk)
* Remarks : Modified for PIC16-LEDSTK1
* Date : First version 1.0 on 19th Nov 2004
* Language : CCS C complier for PIC mid-range MCU, PCM version 3.170, under MPLAB IDE 7.01
* Hardware : PCB 11OCT2004.001, MCU is Microchip's PIC16F877a
* History : Modified for PIC16-LEDSTK1 dated 12 Jan 2006
*********************************************************************************************************
* DESCRIPTION
*
* This module provides an interface to a multiplexed "7-segments x N digits" LED matrix.
*
* To use this driver:
*
* 1) To use this module, the following parameters under define (LED.H):
*
* DISP_N_DIG The total number of segments to display, inc. dp status
* DISP_N_SS The total number of seven-segment digits, e.g "0" "1" "2" is 3-digit
* DISP_PORT1_DIG The address of the DIGITS output port
* DISP_PORT_SEG The address of the SEGMENTS output port
* first_dig_msk The first digit mask for selecting the most significant digit
*
* 2) Allocate a hardware timer which will interrupt the CPU at a rate of at least:
*
* DISP_N_DIG * 60 (Hz)
*
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* CONSTANTS
*********************************************************************************************************
*/
//Assume a PIC 16F877a MCU
//Using PORTA & PORTE for dig select, make sure it is set as digital
#byte DISP_PORT1_DIG = 0x05 /* Port address of DIGITS output for the 1st and 2nd group (PORTA) */
#byte DISP_PORT2_DIG = 0x09 /* Port address of DIGITS output for the 3rd group (PORTE) */
#byte DISP_PORT_SEG = 0x08 /* Port address of SEGMENTS output (PORTD) */
#define set_tris_seg(x) set_tris_d(x) /*Set segment port */
#define set_tris1_dig(x) set_tris_a(x) /*Set digit select port */
#define set_tris2_dig(x) set_tris_e(x) /*Set digit select port */
#define DISP_N_DIG 8 /* Total number of segments (including dp indicators) */
#define DISP_N_SS 3 /* Total number of seven-segment digits (PORTA) of F877 */
#define first_dig_msk 0b000000100 /* First seven-segment digit mask */
//remarks: There is no typo error on first_dig_msk. It is a 9-bits constant because the hardware
//allows extension to 9-digits multiplexing. Actually, if we are using PORT RB as well,
//we can extend to a maximum of 15 digits!
/*
*********************************************************************************************************
* User define if hardware is Common Anode or Cathode
* The application should define if the hardware is a COMMON ANODE or CATHODE
*********************************************************************************************************
*/
#define ALL_OFF 0x00
#define ALL_ON ~ALL_OFF
/*
*********************************************************************************************************
* FUNCTION PROTOTYPES
*********************************************************************************************************
*/
void DispClrScr(void); //API to clear the display
void DispInit(void); //API to initialize the display, call before using other functions
void DispMuxHandler(void); //called by the hardware timer at a rate of at least DISP_N_DIG*60 (Hz)
void DispStr(INT8U dig, char *s); //API to display an ASCII string
void DispStatClr(INT8U dig, INT8U seg);//API to turn off a single LED
/***************************
* dig specifies the digit
* seg specfiies segment to set as follows
* 0 sets segment dp (bit0)
* 1 sets segment g (bit1)
* 2 sets segment f (bit2)
* 3 sets segment e (bit3)
* 4 sets segment d (bit4)
* 5 sets segment c (bit5)
* 6 sets segment b (bit6)
* 7 sets segment a (bit7)
**************************/
void DispStatSet(INT8U dig, INT8U seg); //API to turn on a single LED
/*
*********************************************************************************************************
* FUNCTION PROTOTYPES
* HARDWARE SPECIFIC
*********************************************************************************************************
*/
void DispInitPort(void); //called by DispInit() to initialize the output ports
void DispOutDig(INT16U msk); //digit selector
void DispOutSeg(INT8U seg); //output seven-segment patterns
|
Code: |
/*
*********************************************************************************************************
*
* Multiplexed LED Display Driver
* Reference: Jean J. Labrosse, Embedded Systems Building Blocks
*
* Filename : LED.C
* Programmer : John Leung (www.TechToys.com.hk)
* Remarks : Modified for PIC16-LEDSTK1
* Date : First version 1.0 on 19th Nov 2004
* Language : CCS C complier for PIC mid-range MCU, PCM version 3.170, under MPLAB IDE 7.01
* Hardware : PCB 11OCT2004.001, MCU is Microchip's PIC16F877a
* History : Modified for PIC16-LEDSTK1 dated 12 Jan 2006
*********************************************************************************************************
* DESCRIPTION
*
* This module provides an interface to a multiplexed "7-segments x N digits" LED matrix.
*
* To use this driver:
*
* 1) To use this module, the following parameters under define (LED.H):
*
* DISP_N_DIG The total number of segments to display, inc. dp status
* DISP_N_SS The total number of seven-segment digits (modules)
* DISP_PORT1_DIG The address of the DIGITS output port
* DISP_PORT_SEG The address of the SEGMENTS output port
* first_dig_msk The first digit mask for selecting the most significant digit
*
* 2) Allocate a hardware timer which will interrupt the CPU at a rate of at least:
*
* DISP_N_DIG * 60 (Hz)
*
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL VARIABLES
*********************************************************************************************************
*/
//Remarks: The original Jean's code uses static for local variables; however, this is not valid
//for CCS PICC complier as "static" has no effect under CCS C.
static INT16U DispDigMsk; /* Bit mask used to point to next digit to display */
static INT8U DispSegTbl[DISP_N_SS]; /* Segment pattern table(buffer) for each digit to display, first entry the left most*/
static INT8U DispSegTblIx; /* Index into DispSegTbl[] for next digit to display */
/*$PAGE*/
/*
*********************************************************************************************************
* ASCII to SEVEN-SEGMENT conversion table
* a
* ------
* f | | b
* | g |
* Note: The segments are mapped as follows: ------
* e | | c
* a b c d e f g | d |
* -- -- -- -- -- -- -- -- ------
* D7 D6 D5 D4 D3 D2 D1 D0 (Using PORTD of 16F877a as the segments output port)
*********************************************************************************************************
*/
const INT8U DispASCIItoSegTbl[] = {// ASCII to SEVEN-SEGMENT conversion table
0x00, // ' '
0x00, // '!', No seven-segment conversion for exclamation point
0x44, // '"', Double quote
0x00, // '#', Pound sign
0x00, // '$', No seven-segment conversion for dollar sign
0x00, // '%', No seven-segment conversion for percent sign
0x00, // '&', No seven-segment conversion for ampersand
0x40, // ''', Single quote
0x9C, // '(', Same as '['
0xF0, // ')', Same as ']'
0x00, // '*', No seven-segment conversion for asterix
0x00, // '+', No seven-segment conversion for plus sign
0x00, // ',', No seven-segment conversion for comma
0x02, // '-', Minus sign
0x00, // '.', No seven-segment conversion for period
0x00, // '/', No seven-segment conversion for slash
0xFC, // '0'
0x60, // '1'
0xDA, // '2'
0xF2, // '3'
0x66, // '4'
0xB6, // '5'
0xBE, // '6'
0xE0, // '7'
0xFE, // '8'
0xF6, // '9'
0x00, // ':', No seven-segment conversion for colon
0x00, // ';', No seven-segment conversion for semi-colon
0x00, // '<', No seven-segment conversion for less-than sign
0x12, // '=', Equal sign
0x00, // '>', No seven-segment conversion for greater-than sign
0xCA, //'?', Question mark
0x00, // '@', No seven-segment conversion for commercial at-sign
0xEE, // 'A'
0x3E, // 'B', Actually displayed as 'b'
0x9C, // 'C'
0x7A, // 'D', Actually displayed as 'd'
0x9E, // 'E'
0x8E, // 'F'
0xBC, // 'G', Actually displayed as 'g'
0x6E, // 'H'
0x60, // 'I', Same as '1'
0x78, // 'J'
0x00, // 'K', No seven-segment conversion
0x1C, // 'L'
0x00, // 'M', No seven-segment conversion
0x2A, // 'N', Actually displayed as 'n'
0xFC, // 'O', Same as '0'
0xCE, // 'P'
0x00, // 'Q', No seven-segment conversion
0x0A, // 'R', Actually displayed as 'r'
0xB6, // 'S', Same as '5'
0x1E, // 'T', Actually displayed as 't'
0x7C, // 'U'
0x00, // 'V', No seven-segment conversion
0x00, // 'W', No seven-segment conversion
0x00, // 'X', No seven-segment conversion
0x76, // 'Y'
0x00, // 'Z', No seven-segment conversion
0x00, // '['
0x00, // '\', No seven-segment conversion
0x00, // ']'
0x00, // '^', No seven-segment conversion
0x00, // '_', Underscore
0x00, // '`', No seven-segment conversion for reverse quote
0xFA, // 'a'
0x3E, // 'b'
0x1A, // 'c'
0x7A, // 'd'
0xDE, // 'e'
0x8E, // 'f', Actually displayed as 'F'
0xBC, // 'g'
0x2E, // 'h'
0x20, // 'i'
0x78, // 'j', Actually displayed as 'J'
0x00, // 'k', No seven-segment conversion
0x1C, // 'l', Actually displayed as 'L'
0x00, // 'm', No seven-segment conversion
0x2A, // 'n'
0x3A, // 'o'
0xCE, // 'p', Actually displayed as 'P'
0x00, // 'q', No seven-segment conversion
0x0A, // 'r'
0xB6, // 's', Actually displayed as 'S'
0x1E, // 't'
0x38, // 'u'
0x00, // 'v', No seven-segment conversion
0x00, // 'w', No seven-segment conversion
0x00, // 'x', No seven-segment conversion
0x76, // 'y', Actually displayed as 'Y'
0x00 // 'z', No seven-segment conversion
};
/*
*********************************************************************************************************
* CLEAR THE DISPLAY
*
* Description: This function is called to clear the display.
* Arguments : none
* Returns : none
*********************************************************************************************************
*/
void DispClrScr (void)
{
INT8U i;
for (i = 0; i < DISP_N_SS; i++) { /* Zero the buffer */
DispSegTbl[i] = ALL_OFF;
}
}
/*
*********************************************************************************************************
* DISPLAY DRIVER INITIALIZATION
*
* Description : This function initializes the display driver.
* Arguments : None.
* Returns : None.
*********************************************************************************************************
*/
void DispInit (void)
{
DispInitPort(); // Initialize I/O ports used in display driver
DispDigMsk = first_dig_msk; // digit mask starts from RAx
DispSegTblIx = 0;
DispClrScr(); // Clear the Display
}
/*
*********************************************************************************************************
* DISPLAY NEXT SEVEN-SEGMENT DIGIT
* Description: Called by an interrupt handler to output the segments and select the next digit
* to be multiplexed.
* Arguments : none
* Returns : none
* Notes :
*********************************************************************************************************
*/
void DispMuxHandler (void)
{
/* Insert code to CLEAR INTERRUPT SOURCE here */
DispOutSeg(ALL_OFF); /* Turn OFF segments while changing digits */
DispOutDig(DispDigMsk); /* Select next digit to display */
DispOutSeg(DispSegTbl[DispSegTblIx]); /* Output digit's seven-segment pattern */
if (DispSegTblIx == (DISP_N_SS - 1)) { /* Adjust index to next seven-segment pattern */
DispSegTblIx = 0; /* Index into first segments pattern */
DispDigMsk = first_dig_msk; /* Select the most significant digit */
} else {
DispSegTblIx++;
DispDigMsk >>= 1; /* Select next digit */
}
}
/*
*********************************************************************************************************
* CLEAR STATUS SEGMENT
*
* Description: This function is called to turn OFF a single segment on the display.
* Arguments : dig is the position of the digit where the segment appears (0..DISP_N_DIG-1)
* seg is the segment bit to turn OFF (0..7)
* Returns : none
*********************************************************************************************************
*/
void DispStatClr (INT8U dig, INT8U seg)
{
DispSegTbl[dig] &= ~(1 << seg);
}
/*
*********************************************************************************************************
* SET STATUS SEGMENT
*
* Description: This function is called to turn ON a single segment on the display.
* Arguments : dig is the position of the digit where the segment appears (0..DISP_N_DIG-1)
* seg is the segment bit to turn ON (0..7)
* Returns : none
*********************************************************************************************************
*/
void DispStatSet (INT8U dig, INT8U seg)
{
DispSegTbl[dig] |= 1 <<seg;
}
/*$PAGE*/
/*
*********************************************************************************************************
* DISPLAY ASCII STRING ON SEVEN-SEGMENT DISPLAY
*
* Description: This function is called to display an ASCII string on the seven-segment display.
* Arguments : dig is the position of the first digit where the string will appear:
* 0 for the first seven-segment digit.
* 1 for the second seven-segment digit.
* . . . . . . .
* . . . . . . .
* DISP_N_SS - 1 is the last seven-segment digit.
* s is the ASCII string to display
* Returns : none
* Notes : - Not all ASCII characters can be displayed on a seven-segment display. Consult the
* ASCII to seven-segment conversion table DispASCIItoSegTbl[].
*********************************************************************************************************
*/
void DispStr (INT8U dig, unsigned char *s)
{
while (*s && dig < DISP_N_SS) {
DispSegTbl[dig++] = DispASCIItoSegTbl[*s++ - 0x20];
}
}
/*
*********************************************************************************************************
* I/O PORTS INITIALIZATION
*
* Description: Called by DispInit() to initialize the output ports used in the LED multiplexing.
* Arguments : none
* Returns : none
* Notes :
*********************************************************************************************************
*/
void DispInitPort (void)
{
DISP_PORT_SEG=ALL_OFF; //Turn off segments
DISP_PORT1_DIG=0x00; //Turn off the 1st and 2nd groups (first group uses RA0,A1,A2, 2nd group
// uses RA3,A4,A5)
DISP_PORT2_DIG=0x00; //Turn off the 3rd group (3rd group uses RE0,E1,E2)
set_tris_seg(0x00); //Set segment port an output
set_tris1_dig(0x00); //Set digit port an output
set_tris2_dig(0x00);
}
/*
*********************************************************************************************************
* DIGIT output
*
* Description: This function outputs the digit selector.
* Arguments : msk is the mask used to select the current digit.
* Returns : none
*********************************************************************************************************
*/
void DispOutDig (INT16U msk)
{
DISP_PORT1_DIG=msk; //digit selector here
DISP_PORT2_DIG=msk>>6;
}
/*
*********************************************************************************************************
* SEGMENTS output
*
* Description: This function outputs seven-segment patterns.
* Arguments : seg is the seven-segment pattern to output
* Returns : none
*********************************************************************************************************
*/
void DispOutSeg (INT8U seg)
{
DISP_PORT_SEG=seg; //output seven-segment pattern
}
|
Code: |
/*
*********************************************************************************************************
*
* Interrupt Driven Transmit (Tx) and Receive (Rx) modules
*
* Reference: Embedded C Programming and the Microchip PIC by Barnett, Cox, & O'Cull
*
* Filename : USART.h
* Programmer : John Leung (www.TechToys.com.hk)
* Date : 19th Nov 2004
* Hardware : PCB 11OCT2004.001
*********************************************************************************************************
*/
/* Use dialect of CCS PIC complier, assume a PIC with USART Port (16F877a etc)*/
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,stream=RS232,bits=8)
#define RX_BUFFER_SIZE 32 // UART Receive buffer
#define TX_BUFFER_SIZE 5 // UART Transmit buffer
#define EndOfMsg 0x0d // <cr> as the end of command marker
/*
*********************************************************************************************************
* FUNCTION PROTOTYPES
*********************************************************************************************************
*/
void serial_rx_isr(void); //ISR handler for Rx
INT8U bgetc(void); //Get a character from the UART Receiver buffer
void serial_tx_isr(void); //USART Transmitter interrupt service routine
void bputc(INT8U c); //Write a character to the serial transmit buffer
void CommRxFlush(void); //flush any input characters still in the UART Receiver buffer
|
Code: |
/*
*********************************************************************************************************
*
* Interrupt Driven Transmit (Tx) and Receive (Rx) modules
*
* Reference: Embedded C Programming and the Microchip PIC by Barnett, Cox, & O'Cull
*
* Filename : USART.c
* Programmer : John Leung (www.TechToys.com.hk)
* Date : 15th June 2004
*********************************************************************************************************
*/
// UART Receive buffer
INT8U Rx_Buffer[RX_BUFFER_SIZE+1]; // character array (buffer)
INT8U RX_Wr_Index = 0; // index of next char to be put into the buffer
INT8U RX_Rd_Index = 0; // index of next char to be fetched from the buffer
INT8U RX_Counter = 0; // total count of characters in the buffer
BOOLEAN RX_Buffer_Overflow = FALSE; // this flag is set on UART Receiver buffer overflow
BOOLEAN EndOfMsg_Flg = FALSE; // End-of-Message flag to indicate EndOfMsg has been received
// UART Transmit buffer
INT8U TX_Buffer [TX_BUFFER_SIZE+1]; // character array (buffer)
INT8U TX_Rd_Index = 0; // index of next char to be put into the buffer
INT8U TX_Wr_Index = 0; // index of next char to be fetched from the buffer
INT8U TX_Counter = 0; // total count of characters in the buffer
// USART Receiver interrupt service routine, slightly modified according to Jean J. Labrosse's routine
void serial_rx_isr()
{
if(++RX_Counter <= RX_BUFFER_SIZE) //if Rx Ring buffer not full, and keep character count
{
Rx_Buffer[RX_Wr_Index] = getc(); // put received char in buffer
if(Rx_Buffer[RX_Wr_Index] == EndOfMsg) //set EndOfMsg_Flg for command process
EndOfMsg_Flg=TRUE;
if(++RX_Wr_Index > RX_BUFFER_SIZE) // wrap the pointer
RX_Wr_Index = 0;
} else {
RX_Counter = RX_BUFFER_SIZE; // if too many chars came
RX_Buffer_Overflow = TRUE; // in before they could be used, that could cause an error
}
}
// Get a single character from the UART Receiver buffer
INT8U bgetc(void)
{
INT8U c;
while(RX_Counter == 0) // wait for a character...
;
c = Rx_Buffer[RX_Rd_Index]; // get one (first) from the buffer..
if(++RX_Rd_Index > RX_BUFFER_SIZE) // wrap the pointer
RX_Rd_Index = 0;
if(RX_Counter)
RX_Counter--; // keep a count (buffer size)
return c;
}
// USART Transmitter interrupt service routine
void serial_tx_isr()
{
//if there are characters to be transmitted....
if(TX_Counter != 0)
{
putc(TX_Buffer[TX_Rd_Index]);
// send char out port
// test and wrap the pointer
if(++TX_Rd_Index > TX_BUFFER_SIZE)
TX_Rd_Index = 0;
TX_Counter--; // keep track of the counter
if (TX_Counter == 0)
disable_interrupts(int_tbe);
}
}
// write a character to the serial transmit buffer
void bputc(INT8U c)
{
INT8U restart = 0;
while(TX_Counter > (TX_BUFFER_SIZE-1))
; // WAIT!! Buffer is getting full!!
if(TX_Counter == 0) // if buffer empty, setup for interrupt
restart = 1;
TX_Buffer[TX_Wr_Index++]=c; // jam the char in the buffer..
if(TX_Wr_Index > TX_BUFFER_SIZE) // wrap the pointer
TX_Wr_Index = 0;
// keep track of buffered chars
TX_Counter++;
// do we have to "Prime the pump"?
if(restart == 1)
enable_interrupts(int_tbe);
}
//This function flushes any input characters still in the RX UART buffer
//This must be called whenever RX_Buffer_Overflow = TRUE
void CommRxFlush(void)
{
disable_interrupts(int_rda); //disable USART Rx interrupt
//reset all Rx indexes and counters
RX_Wr_Index = 0;
RX_Rd_Index = 0;
RX_Counter = 0;
RX_Buffer_Overflow = FALSE;
#ifdef EoM
EndOfMsg_Flg = FALSE;
#endif
enable_interrupts(int_rda);
}
|
Code: |
/*
*********************************************************************************************************
*
* CCS PICC Complier Specific Code
*
*
* File : OS_CPU.H
* By : John Leung for CCS PICC complier for low & mid - range CPUs
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* DATA TYPES
* (Compiler Specific, CCS PICC in this case)
*********************************************************************************************************
*/
typedef unsigned char INT8U; /* Unsigned 8 bit quantity */
typedef signed char INT8S; /* Signed 8 bit quantity */
typedef unsigned long int INT16U; /* Unsigned 16 bit quantity */
typedef long int INT16S; /* Signed 16 bit quantity */
typedef unsigned int32 INT32U; /* Unsigned 32 bit quantity */
typedef signed int32 INT32S; /* Signed 32 bit quantity */
typedef float FP32; /* Single precision floating point */
|
Code: |
////////////////// Driver to generate musical tones /////////////////////
//// ////
//// generate_tone(frequency, duration) Generates wave at set ////
//// frequency (Hz) for set ////
//// duration (ms) ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS ////
//// C compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, ////
//// reproduction or distribution is permitted without written ////
//// permission. Derivative programs created using this software ////
//// in object code form are not restricted in any way. ////
/////////////////////////////////////////////////////////////////////////
#ifndef MUSIC_NOTES
#define MUSIC_NOTES
/*
// NOTE FREQUENCY
// Octave0 Octave1 Octave2 Octave3
const long C_NOTE[4] ={ 262, 523, 1047, 2093};
const long Db_NOTE[4] ={ 277, 554, 1109, 2217};
const long D_NOTE[4] ={ 294, 587, 1175, 2349};
const long Eb_NOTE[4] ={ 311, 622, 1245, 2489};
const long E_NOTE[4] ={ 330, 659, 1329, 2637};
const long F_NOTE[4] ={ 349, 698, 1397, 2794};
const long Gb_NOTE[4] ={ 370, 740, 1480, 2960};
const long G_NOTE[4] ={ 392, 784, 1568, 3136};
const long Ab_NOTE[4] ={ 415, 831, 1661, 3322};
const long A_NOTE[4] ={ 440, 880, 1760, 3520};
const long Bb_NOTE[4] ={ 466, 923, 1865, 3729};
const long B_NOTE[4] ={ 494, 988, 1976, 3951};
#endif
*/
#define TONE_PIN PIN_C2
void do_delay(int ms_delay, int num_ms, int us_delay, int num_us) {
int i;
for(i=0;i<num_ms;i++)
delay_ms(250);
delay_ms(ms_delay);
for(i=0;i<num_us;i++)
delay_us(250);
delay_us(us_delay);
}
void generate_tone(long frequency, long duration)
{
int32 total_delay_time; // in microseconds
long total_ms_delay_time, total_us_delay_time;
int num_us_delays, num_ms_delays, ms_delay_time, us_delay_time;
long num_periods;
total_delay_time = (1000000/frequency)/2-10; // calculate total delay time (10 for error)
total_ms_delay_time = total_delay_time/1000; // total delay time of ms
num_ms_delays = total_ms_delay_time/250; // number of 250ms delays needed
ms_delay_time = total_ms_delay_time%250; // left over ms delay time needed
total_us_delay_time = total_delay_time%1000; // total delay time of us (ms already acounted for)
num_us_delays = total_us_delay_time/250; // number of 250us delays needed
us_delay_time = total_us_delay_time%250; // left over us delay time needed
num_periods = ((int32)duration*1000)/(1000000/frequency);
while((num_periods--) != 0)
{
do_delay(ms_delay_time, num_ms_delays, us_delay_time, num_us_delays);
output_high(TONE_PIN);
do_delay(ms_delay_time, num_ms_delays, us_delay_time, num_us_delays);
output_low(TONE_PIN);
}
return;
}
|
|
|