📄 simuart.c
字号:
/****************************************************************
** *
** FILE : SimUART.C *
** COPYRIGHT : (c) 2001 .Xiamen Yaxon NetWork CO.LTD *
** *
** *
** 2006.3.30 *
****************************************************************/
#define _SIMUART_C_ 1
#include "includes.h"
#include "bsp.h"
#include "simuart.h"
#pragma O0
/*
********************************************************************************
* DEFINE CONFIG PARAMETERS
********************************************************************************
*/
#define SOFT_INTERRUPT_PRIO 5 /*定义中断优先级*/
#define IRQ2_INTERRUPT_PRIO 6
#define TIMER2_PRIO 7
//#define BASE_BAUD 2400
#define SELECT_CLK MCK/8
#define PRESCALE 4
//#define VALUE_CLOCK SELECT_CLK / (BASE_BAUD * PRESCALE)
#define BITLENGTH -PRESCALE+1 /*每发送接收一位定时器中断次数*/
#define HALFBIT 0 //(-PRESCALE+1)/2
#define SIM_TXD AT91C_P10_IRQ1 /* 发送针 */
#define SIM_RXD AT91C_P11_IRQ2 /* 接收针 */
/*
********************************************************************************
* DEFINE MODULE VARIANT
********************************************************************************
*/
static INT32U txpin; /* 发送脚 */
static INT32U rxpin; /* 接收脚 */
static INT32U rxavail; /* 接收有效标志 */
static INT8U txfull; /* 发送缓冲器器满标志 */
static INT8U rxfull; /* 接收缓冲器器满标志 */
static INT8U txshift; /* 发送移位寄存器 */
static INT8U rxshift; /* 接收移位寄存器 */
static INT8U txcnt; /* 发送位计数器 */
static INT8U rxcnt; /* 接收位计数器 */
static INT8S txtime; /* 计数发送每位定时器中断次数 */
static INT8S rxtime; /* 计数接收每位定时器中断次数 */
static INT8U txdat; /* 发送保持寄存器 */
static INT8U rxbuf; /* 接收保持寄存器 */
static INT8U TimRxBusy, TimTxBusy; /* 发送接收忙标志 */
extern void SimUart_sys_handler (void);
/*************************************************************************
* TxStart - 发送起始位
**************************************************************************/
static void TxStart(void) /*模拟串口发送起始位过程*/
{
AT91F_PIO_ClearOutput( AT91C_BASE_PIO, txpin); /*清零TXD0脚*/
txshift = txdat; /*把发送的数据送入发送移位器*/
txfull = 0;
txcnt = COUNT_DATA; /*发送数据位计数*/
txtime = BITLENGTH; /*发送一位定时器中断次数*/
}
/*************************************************************************
* TxData - 发送数据位
**************************************************************************/
static void TxData(void) /*模拟串口发送数据位过程*/
{
if (txshift & 0x01) {
AT91F_PIO_SetOutput( AT91C_BASE_PIO, txpin); /*置位输出*/
} else {
AT91F_PIO_ClearOutput( AT91C_BASE_PIO, txpin); /*清零输出*/
}
txshift = txshift>>1; /*移位下一个要发送的位到最低位*/
txcnt++; /*发送位计数*/
txtime = BITLENGTH; /*设置定时器中断次数*/
}
/*************************************************************************
* TxStop - 发送停止位并触发软件中断,以判断是否还要发送!
**************************************************************************/
static void TxStop(void) /*模拟串口发送停止位过程*/
{
AT91F_PIO_SetOutput(AT91C_BASE_PIO, txpin); /*置位输出*/
TimTxBusy = 0;
sended_tx = 1;
//txfull = 0;
if (TimRxBusy == 0) {
AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS; /*禁止止定时器*/;
}
AIC_Trigger(AT91C_ID_SYS);
}
/*************************************************************************
* RxStart - 接收起始位,并判断其正确性
**************************************************************************/
static void RxStart(void) /*模拟串口接收起始位过程*/
{
if (rxavail == 0 ) { /*接收的是起始位?*/
rxcnt = COUNT_DATA;
rxtime = BITLENGTH; /*是,设置定时器中断次数*/
} else { /*否则,中止接收并停止定时器*/
TimRxBusy = 0;
if(TimTxBusy == 0) {
AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS; /*停止定时器*/;
}
AIC_Int_Enable(AT91C_ID_IRQ2); /*接收中断使能*/
}
}
/*************************************************************************
* RxData - 接收数据位
**************************************************************************/
static void RxData(void) /*模拟串口接收数据位过程*/
{
rxshift = rxshift >> 1;
if (rxavail) {
rxshift |= 0x80; /*置位最高位*/
} else {
rxshift &= 0x7f; /*清零高位*/
}
rxcnt++;
rxtime = BITLENGTH;
}
/*************************************************************************
* RxStop - 接收停止位,判断其正确性,若正确,触发软件中断,进行数据处理,不正确则丢弃
**************************************************************************/
static void RxStop(void) /*模拟串口接收停止位过程*/
{
rxbuf = rxshift;
rxfull = 1;
TimRxBusy = 0;
if (TimTxBusy == 0) {
AT91C_BASE_TC2->TC_CCR=AT91C_TC_CLKDIS; /*停止定时器*/;
}
AIC_Int_Enable(AT91C_ID_IRQ2);
if (rxavail) {
recved_rx = 1;
AIC_Trigger(AT91C_ID_SYS);
}
//WriteSimUART(rxbuf);
}
/*************************************************************************
* Rs232Tx - 启动发送一位
**************************************************************************/
static void Rs232Tx(void) /*模拟串口发送一位过程*/
{
if (txcnt == STARTBIT_FLAG) {
TxStart();
} else if (txcnt == STOPBIT_FLAG) {
TxStop();
} else {
TxData();
}
}
/*************************************************************************
* Rs232Rx - 启动接收一位
**************************************************************************/
static void Rs232Rx(void)
{
rxavail=((AT91F_PIO_GetInput(AT91C_BASE_PIO)) & SIM_RXD);
if (rxcnt == STARTBIT_FLAG) {
RxStart();
} else if (rxcnt == STOPBIT_FLAG) {
RxStop();
} else {
RxData();
}
}
/*************************************************************************
* WriteSimUART - 从模拟串口发送一个字节
**************************************************************************/
void WriteSimUART(INT8U ch)
{
sended_tx = 0;
txfull = 1;
txdat = ch;
txcnt = STARTBIT_FLAG;
txtime = BITLENGTH;
if(TimRxBusy == 0) {
AT91C_BASE_TC2->TC_CCR = AT91C_TC_SWTRG | AT91C_TC_CLKEN; //软件触发定时器2
}
TimTxBusy = 1;
}
/*************************************************************************
* ReadSimUART - 读模拟串口
**************************************************************************/
INT8U ReadSimUART(void)
{
recved_rx = 0;
return rxbuf;
}
BOOLEAN SimUARTRecv(void)
{
return recved_rx;
}
BOOLEAN SimUARTReady(void)
{
return sended_tx;
}
/*************************************************************************
* TC2_handler - 判断中断情况,启动收发
**************************************************************************/
static void TC2_handler(void)
{
TC_Ioctl(SYS_TC2, TC_CMD_INT_ACK, 0);
if (TimTxBusy == 1) {
if (txtime < 0) {
txtime++ ;
} else {
Rs232Tx();
}
}
if (TimRxBusy == 1) {
if (rxtime < 0) {
rxtime++ ;
} else {
Rs232Rx();
}
}
}
/*************************************************************************
* Init_Timer2 - 初始化定时起2,用来接收发送的计时
**************************************************************************/
static void Init_Timer2(INT16U baud)
{
TC_Open (SYS_TC2, TC_CLKS_MCK8|AT91C_TC_CPCTRG|AT91C_TC_WAVE|AT91C_TC_EEVT_BOTH, 0, 0, 0);
AIC_Install( AT91C_ID_TC2,TIMER2_PRIO,AIC_EDGE_NEGATIVE, TC2_handler);
AT91C_BASE_TC2->TC_IER = AT91C_TC_CPCS;
AT91C_BASE_TC2->TC_RC = (SELECT_CLK/(baud * PRESCALE));
}
/*************************************************************************
* IRQ2_handler
**************************************************************************/
static void IRQ2_handler(void)
{
if(TimTxBusy == 0) {
AT91C_BASE_TC2->TC_CCR = AT91C_TC_SWTRG|AT91C_TC_CLKEN;
}
AIC_Int_Disable(AT91C_ID_IRQ2); /*SimUARTchan中断禁止*/
TimRxBusy = 1;
rxtime = HALFBIT;
rxcnt = STARTBIT_FLAG;
}
/*************************************************************************
* InitSimUART - 初始化模拟串口,安装定时器和外部并口中断向量,但未使能中断
**************************************************************************/
void InitSimUART(INT16U baud)
{
txpin = SIM_TXD;
rxpin = SIM_RXD;
txfull = 0;
rxfull = 0;
txcnt = 0;
rxcnt = 0;
sended_tx = 1;
recved_rx = 0;
TimTxBusy = 0;
TimRxBusy = 0;
AT91F_PIO_CfgOutput( AT91C_BASE_PIO, txpin ) ;
AT91F_PIO_SetOutput( AT91C_BASE_PIO, txpin ) ;
PIO_Close(AT91C_P11_IRQ2);
AIC_Install( AT91C_ID_IRQ2,IRQ2_INTERRUPT_PRIO,AIC_LEVEL_LOW, IRQ2_handler);
Init_Timer2(baud);
AIC_Install( AT91C_ID_SYS,SOFT_INTERRUPT_PRIO,AIC_EDGE_POSITIVE, SimUart_sys_handler);
AIC_Int_Enable(AT91C_ID_SYS);
}
/*************************************************************************
* EnableSimUART - 启动并使能模拟串口
**************************************************************************/
void EnableSimUART(void)
{
AT91F_PS_EnablePeriphClock ( AT91C_BASE_PS, 1 << AT91C_ID_PIO ) ;
AIC_Int_Enable(AT91C_ID_IRQ2);
AIC_Int_Enable(AT91C_ID_TC2);
AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN;
sended_tx = 1;
}
/*************************************************************************
* DisableSimUART - 关闭模拟串口
**************************************************************************/
void DisableSimUART(void)
{
AIC_Int_Disable(AT91C_ID_IRQ2);
AIC_Int_Disable(AT91C_ID_TC2);
sended_tx = 0;
recved_rx = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -