⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stdio_uart.c

📁 在BF533上用汇编实现的串口初始化程序
💻 C
字号:
///////////////////////////////////////////////////////////////
// 
//  STDIO_UART
//
// Creates new STDIO Device Driver for UART I/O
//
//(C) Copyright 2004 - Analog Devices, Inc.  All rights reserved.
//File Name:        stdio_uart.c
//Date Modified:	03/19/04	
//
//Hardware:		ADSP-BF533 EZ-KIT Lite Board
//
//Special Connections:  
//		- EIA-232 Serial Cable (1:1)
//		- Terminal Program (i.e. Hyperterminal for Windows)
//		- 2400 bits per second (default)
//		- 8-bit, no parity, 1 stop bit
//		- no handshake
//		- echo off
//
//Purpose:	
//          - Registering New STDIO Device Driver for UART I/0
//          - Redirect Stdin/Stdout to New STDIO Device Driver
//          - (optional)Autobaud Detection using GP Timer 2
//	
//Steps:
//          - Build and Run 
//          - Open a Terminal Program (i.e. Hyperterminal for Windows)
//          - "Hello World" will print to Terminal Program
//	      - "Type in something, press <Enter>, and I'll repeat it backwards!"
//
///////////////////////////////////////////////////////////////

#include <device.h>
#include <ccblkfn.h>
#include <cdefBF533.h>
#include <sys/exception.h>
#include <stdio.h>


int   UART_init  (struct DevEntry *dev);
int   UART_open  (const char *name, int mode);
int   UART_close (int fd);
int   UART_write (int fd, unsigned char *buf, int size);
int   UART_read  (int fd, unsigned char *buf, int size);
long  UART_seek  (int fd, long offset, int whence);


DevEntry UART_DevEntry =
{
	0,
	NULL,
	UART_init,
	UART_open,
	UART_close,
	UART_write,
	UART_read,
	UART_seek,
	
	dev_not_claimed,
	dev_not_claimed,
	dev_not_claimed
};


void UART_inititialize(int divisor);
void UART_disable(void);
int  UART_detectAutobaud(void);
void UART_waitForTransferCompletion(void);
void UART_putc(char c);
void UART_puts(char *c);
char UART_getc(void);
int  UART_gets(char *str, int max);
int  UART_detectAutobaud(void);
int  UART_getSCLK(void);

#define MEGA     1000000 
extern unsigned short CLKIN;

///////////////////////////////////////////////////////////////
int   UART_init  ( struct DevEntry *dev )
{
	int period=0, divisor=0, SCLK=0;

	if ( 0 == (int) dev->data )
	{
		// If the baud rate is specified as zero, then autobaud.
		period = UART_detectAutobaud();
		
		//Apply formula divisor = period / (16 x 8 bits)	
		divisor = period >> 7;
	}
	else
	{  // use system clock to calc divisor
	
		SCLK = UART_getSCLK();
		divisor = SCLK  / ( (int) dev->data * 16);
	}

	UART_inititialize(divisor);	
	
	return 0;
}
///////////////////////////////////////////////////////////////
int   UART_open  (const char *name, int mode)
{
	return 0;
}
///////////////////////////////////////////////////////////////
int   UART_write (int fd, unsigned char *buf, int size)
{
	
	int i = 0;
	
	for ( ; i < size; ++i)	UART_putc( *buf++ );
		
	UART_waitForTransferCompletion();
		
	return 0;
}
///////////////////////////////////////////////////////////////
int   UART_read  (int fd, unsigned char *buf, int size)
{
	fflush( (FILE *) fd );  //for printf
	int result = UART_gets( (char *) buf, size );
	return result;
}

///////////////////////////////////////////////////////////////
long   UART_seek  (int fd, long offset, int whence)
{
	return 0;
}

///////////////////////////////////////////////////////////////
int   UART_close (int fd)
{
	UART_disable();
	return 0;
}
///////////////////////////////////////////////////////////////
//Configures UART in 8 data bits, no parity, 1 stop bit mode.
///////////////////////////////////////////////////////////////
void UART_inititialize(int divisor)
{
	// enable UART clock. 
	*pUART_GCTL = UCEN;
	
	// Read period value and apply formula:  divisor = period/16*8
	// Write result to the two 8-bit DL registers (DLH:DLL).
	*pUART_LCR = DLAB;
	*pUART_DLL = divisor;
	*pUART_DLH = divisor>>8;

	// Clear DLAB again and set UART frame to 8 bits, no parity, 1 stop bit. 

	*pUART_LCR = WLS(8);			
}
///////////////////////////////////////////////////////////////
//disable UART clock, after polling the TEMT bit
///////////////////////////////////////////////////////////////
void UART_disable(void)
{
	UART_waitForTransferCompletion();
	*pUART_GCTL = 0;
}
///////////////////////////////////////////////////////////////
//poll the TEMT bit in LSR reg and wait until all data shifted out.
///////////////////////////////////////////////////////////////
void UART_waitForTransferCompletion(void)
{	
	while (!(*pUART_LSR & TEMT)) { }; // wait
	ssync();
}
///////////////////////////////////////////////////////////////
//transmit character by polling the THRE bit in the LSR register.
///////////////////////////////////////////////////////////////
void UART_putc(char c)
{
	while (!(*pUART_LSR & THRE)) { }; //wait
	*pUART_THR = c;		
}
//////////////////////////////////////////////////////////////
void UART_puts(char *c)
{
	while (*c)
	{	
		UART_putc(*c);
		c++;
	}
}
///////////////////////////////////////////////////////////////
//receive character by polling the DR bit in the LSR register.
///////////////////////////////////////////////////////////////
char UART_getc(void)
{
	char c;
	while (!(*pUART_LSR & DR)) { }; //wait
	c = *pUART_RBR;
	return c;
}
///////////////////////////////////////////////////////////////
//receive an LF ('ENTER') by polling the DR bit in the LSR register.
///////////////////////////////////////////////////////////////
int UART_gets(char *str, int max)
{
	int i;
	for(i = 0; i < max; i++)
	{
		str[i] = UART_getc();
		if (str[i] == 13)
		{
			return i+1;
		}
	}
	return max;
}
///////////////////////////////////////////////////////////////
// Start Auto Baud detection by entering "@" inside Terminal Program
///////////////////////////////////////////////////////////////
int UART_detectAutobaud(void)
{
	int period = 0;

	// Activate Loopback mode in order the receive channel is disconnected 
	// from RX pin during autobaud detection.
	
	*pUART_MCR = LOOP_ENA;			
	
	// Setup Timer 2 Controller to do the autobaud detection. Timer captures
	// duration between two falling edges. It expects a '@' (ASCII 0x40) 
	// character. 8-bit, no parity assumed.
	// Disable Timer 2 first, in case there was an unexpected history.  
	
	*pTIMER_DISABLE  = TIMDIS2;
	*pTIMER_STATUS   = TRUN2 | TOVL_ERR2 | TIMIL2;
	
	// Capture from UART RxD pin. Select period capture from falling edge to 
	// falling edge. Enable IRQ_ENA, but don't enable the interrupt at system 
	// level (SIC). 
	
	*pTIMER2_CONFIG = TIN_SEL | IRQ_ENA | PERIOD_CNT | WDTH_CAP;

	// Start the timer and wait until the according interrupt latch bit TIMIL2
	// in the TIMER_STATUS register is set. Then, two falling edges on the RxD
	// pin have been detected.
	
	*pTIMER_ENABLE = TIMEN2;

	// Enable the UART
	
	*pUART_GCTL = UCEN;
	

	while (!(*pTIMER_STATUS & TIMIL2)) {}; //wait

	// Disable Timer 2 again  
	*pTIMER_DISABLE = TIMDIS2;
	*pTIMER_STATUS = TRUN2 | TOVL_ERR2 | TIMIL2;
	
	// Save period value
	period = *pTIMER2_PERIOD;
 		
	// In order to support also half-duplex connections, we need to delay any 
	// transmission, in order the sent character does not overlap the autobaud
	// pattern.
	// Use Timer 2 to perform this delay. Note that the Period Register still
	// contains the proper value and the Width Register is not used.
	
	*pTIMER2_CONFIG = OUT_DIS | IRQ_ENA | PERIOD_CNT | PWM_OUT;	
	*pTIMER_ENABLE = TIMEN2;	
	
	while (!(*pTIMER_STATUS & TIMIL2)) { }; //wait

	// Disable Timer 2 again
	
	*pTIMER_DISABLE = TIMDIS2;
	*pTIMER_STATUS = TRUN2 | TOVL_ERR2 | TIMIL2;	
			
	// Deactive Loopback mode again
	*pUART_MCR = 0;	
	
	return period;
}

///////////////////////////////////////////////////////////////
//CLKIN is the input clock.The ADSP-BF533 EZ-Kits CLKIN is 27MHz 
//This function will check what the system clock is based
//on the MSEL, DF, and SSEL values in the PLL_CTL and PLL_DIV registers.
///////////////////////////////////////////////////////////////
int UART_getSCLK()
{
	unsigned short tempPLLCTL, tempPLLDIV;	
	unsigned short MSEL, SSEL, DF, VCO, SCLK;
	
	tempPLLCTL = *pPLL_CTL;
	tempPLLDIV = *pPLL_DIV;

	//get MSEL, SSEL, DF
	MSEL = ((tempPLLCTL & 0x7E00) >> 9);
	SSEL = tempPLLDIV & 0x000f;
	DF   = tempPLLCTL & 0x0001;
	
	if(DF == 1) CLKIN = CLKIN/2;
	
	VCO  = MSEL * CLKIN;
	SCLK = VCO/SSEL;  
	
	return  SCLK * MEGA;
}
///////////////////////////////////////////////////////////////


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -