首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

基于Xilinx FPGA的μC/OS-II的串行驱动应用

基于Xilinx FPGA的μC/OS-II的串行驱动应用

看天气越来越冷了,创作的激情可不能冷却。
今天主要演示一下使用串行口0用中断方式来发送和接受数据。
UART0 原理框图如下:


UART0 是一个具有帧错误检测和地址识别硬件的增强型串行口。UART0 可以工作在全双工异步方式或半双工同步方式,并且支持多处理器通信。接收数据被暂存于一个保持寄存器中,这就允许UART0 在软件尚未读取前一个数据字节的情况下开始接收第二个输入数据字节。一个接收覆盖位用于指示新的接收数据已被锁存到接收缓冲器而前一个接收数据尚未被读取。

对UART0 的控制和访问是通过相关的特殊功能寄存器即串行控制寄存器(SCON0)和串行数据缓冲器(SBUF0)来实现的。一个SBUF0 地址可以访问发送寄存器和接收寄存器。读操作将自动访问接收寄存器,而写操作自动访问发送寄存器。

程序流程
实验步骤编写、编译、装载,连续运行程序,在PC上用超级终端来显示和发送数据。本程序会通过串口发送进入系统的欢迎信息,并在超级终端运行简单的shell-v命令,reboot命令以及命令错误的提示信息,其中v命令显示操作系统版本信息,reboot命令重新启动系统。
实验程序#include "includes.h"

/* Constants */
#define SYSCLK 25000000
#define BAUDRATE 9600 //波特率默认为9600
#define RX_LENGTH 16
sbit P35=P3^5;

/*
*********************************************************************************************************
* VARIABLES
*********************************************************************************************************
*/

OS_STK TaskStkStart[MaxStkSize];
OS_STK TaskStkA[MaxStkSize];
OS_STK TaskStkB[MaxStkSize];
OS_STK TaskStkC[MaxStkSize];
OS_STK TaskStkD[MaxStkSize];
OS_STK TaskStkE[MaxStkSize];

TASK_USER_DATA xdata TaskUserData[20];

/*
*********************************************************************************************************
* FUNCTION PROTOTYPES
*********************************************************************************************************
*/
void TaskStart(void*) reentrant;
void TaskA(void*) reentrant;
void TaskB(void*) reentrant;
void TaskC(void*) reentrant;



/*
*********************************************************************************************************
* MAIN
*********************************************************************************************************
*/
void main(void)
{

config();
OSInit();

strcpy(TaskUserData[0].TaskName, "TaskStart");
//OSTaskCreate(TaskStart, (void *)0, TaskStkStart,0);
OSTaskCreateExt(TaskStart, (void *)0, TaskStkStart,0,0,&TaskStkStart[MaxStkSize-1],
MaxStkSize,&TaskUserData[0],OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
OSStart();
}

/*
*********************************************************************************************************
* STARTUP TASK
*********************************************************************************************************
*/
void TaskStart(void *pdat) reentrant
{

pdat=pdat;

InitTimer0();

OSStatInit();

strcpy(TaskUserData[1].TaskName, "TaskA");
strcpy(TaskUserData[2].TaskName, "TaskB");
OSTaskCreateExt(TaskA, (void *)0, TaskStkA,1,1,&TaskStkA[MaxStkSize-1],
MaxStkSize,&TaskUserData[1],OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
OSTaskCreateExt(TaskB, (void *)0, TaskStkB,2,2,&TaskStkB[MaxStkSize-1],
MaxStkSize,&TaskUserData[2],OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

//OSTaskCreate(TaskA, (void *)0, TaskStkA,1);
//OSTaskCreate(TaskB, (void *)0, TaskStkB,2);
//OSTaskCreate(TaskC, (void *)0, TaskStkC,7);
//OSTaskCreate(TaskD, (void *)0, TaskStkD,5);

for(;;)
{
//OSTaskStkChk(0, &TaskUserData[0].dat);
//OSCtxSwCtr = 0;
OSTimeDlyHMSM(0, 0, 1, 0);
}
}
/****************************************************************************************
* TaskA():系统运行指示灯
****************************************************************************************/
void TaskA( void *pData ) reentrant
{
pData = pData;

for(;;)
{
P35=~P35;
//OSTaskStkChk(1, &TaskUserData[1].dat);
OSTimeDlyHMSM(0, 0, 0, 100);
}
}


/****************************************************************************************
* TaskB():接受串口命令
****************************************************************************************/
void TaskB(void *pdat) reentrant
{
extern bit RX_Ready; // '1' means RX string received
extern char idata RX_Buf[RX_LENGTH]; // receive string storage buffer

pdat=pdat;

UART0_Init();

Welcome();

while (1)
{ // echo messages
if (RX_Ready == 1) // wait for string
{


if (RX_Buf[0] == 'r' && RX_Buf[1] == 'e'&& RX_Buf[2] == 'b' && RX_Buf[3] == 'o'
&& RX_Buf[4] == 'o'&& RX_Buf[5] == 't'&& RX_Buf[6] == '\0')
{
CMD_Reboot();
}

switch (RX_Buf[0])
{

case 'v' :
CMD_V();
break;
default:
CMD_Error();
}

cmdline: CMD_Line();
RX_Ready = 0; // free the receiver
}
//OSTaskStkChk(2, &TaskUserData[2].dat);
OSTimeDlyHMSM(0, 0, 0, 500);
}
}/*显示欢迎信息*/
void Welcome(void)
{
EA = 0;
TI0 = 1;
printf("\n/********************uC/OS-II, The Real-Time Kernel********************/\n");
printf("\n Welcome to the uC/OS-II command mode! \n");
printf("\n/**********************************************************************/\n\n");
printf(">");
TI0 = 0;
EA = 1;
}

/****************************************************************************************
* void CMD_V():V命令功能函数,显示系统版本号
* 参数:无
****************************************************************************************/
void CMD_V(void)
{
EA = 0;
TI0 = 1;
printf( "uC/OS-II V%1d.%02d", OSVersion() / 100, OSVersion() % 100);
TI0 = 0;
EA = 1;
}
/****************************************************************************************
* void CMD_Reboot():reboot命令功能函数,重新启动
* 参数:无
****************************************************************************************/
void CMD_Reboot(void)
{
RSTSRC |= 0x02;
}
/****************************************************************************************
* void CMD_ERROR():命令不匹配时的功能函数
* 参数:无
****************************************************************************************/
void CMD_Error(void)
{
EA = 0;
TI0 = 1;

printf("Bad command.\nPlease input help or ? get for help.\n");

TI0 = 0;
EA = 1;
}
void CMD_Line(void)
{
EA = 0;
TI0 = 1;
printf("\n\n>");
TI0 = 0;
EA = 1;
}
//串口0中断服务程序
void UART0_ISR(void) interrupt 4
{

static unsigned char RX_index = 0; // receive buffer index
unsigned char the_char;

if (RI0 == 1) // handle receive function
{
RI0 = 0; // clear RX complete indicator
if (RX_Ready != 1) // check to see if message pending
{
the_char = SBUF0;
if (the_char != '\r') // check for end of message
{ // store the character
RX_Buf[RX_index] = the_char;
// increment buffer pointer and wrap if necessary
if (RX_index < (RX_LENGTH - 2))
{
RX_index++;
}
else
{
RX_index = 0; // if length exceeded,
RX_Ready = 1; // post message complete, and
// NULL-terminate string
RX_Buf[RX_index-1] = '\0';
}
}
else
{
RX_Buf[RX_index] = '\0'; // NULL-terminate message
RX_Ready = 1; // post message ready
RX_index = 0; // reset RX message index
}
}
else
{
// ignore character -- previous message has not been processed
}
}
else if (TI0 == 1) // handle transmit function
{
TI0 = 0; // clear TX complete indicator
the_char = *TX_ptr; // read next character in string
if (the_char != '\0')
{
SBUF0 = the_char; // transmit it
TX_ptr++; // get ready for next character
}
else
{ // character is NULL
TX_Ready = 1; // indicate ready for next TX
}
}
}

// 串口初始化函数
void UART0_Init()
{
XBR0 |= 0x04; //RX0,TX0连到2个端口引脚
XBR2 |= 0x40; //交叉开关允许
P0MDOUT |= 0x03; //RX0,TX0口设为推挽方式,连在P0.1,P0.0上

SCON0= 0x50; //方式1: 8 位UART 可变波特
TMOD |= 0x20; //定时器1为自动重装载的8 位计数器/定时器
TMOD |= 0x20; //定时器1为自动重装载的8 位计数器/定时器
TH1 = -(SYSCLK/BAUDRATE/16);
TR1 = 1; //启动定时器1
CKCON |= 0x10;//定时器1 使用系统时钟
PCON |= 0x80;//SMOD0=1

EA = 1; //开中断
ES0 = 1;

TX_Ready = 1; // indicate TX ready for transmit
RX_Ready = 0; // indicate RX string not ready
TX_ptr = NULL;

}
程序有点长,但是我都注释了的,有存在疑惑的地方可以给我留言,很多时候修改一下就能应用到其他地方了。
文章来源:snifer
记录学习中的点点滴滴,让每一天过的更加有意义!
返回列表