终于在几天的学习下又有进一步的突破了,LOOK系统也有个大概的概念了,且在学习LOOK的过程中也在思考用C++如何写程序,和C语言写程序有比较大的不同了,毕竟它的精华是面向对象的思想,刚开始写一直用LOOK里类的派生类,发现自己被LOOK类绑架了:L,没事就用task_t类,唉,没抓住他们特点就有点胡来的感觉,现在没事就自己建个类,要用到LOOK类的功能才从LOOK派生。 最近学了下interrupt_t和mbox<T>类,实现了几个简单的功能,下面来讲讲这些类:
interrut_t是当使用中断功能时才用该类派生个中断类,该类最重要也就是
interrupt_t * attach (uintptr_t irq)
挂接本中断对象到指定的中断号上
该功能实现当前的中断对象和对应的中断向量类进行相关联,无聊找出了其中的一些关系
这段是中断的attach函数,看到和vector::table[中断号].attach(this),还有vector_t::attach
__OPT_INLINE__ look::interrupt_t* look::interrupt_t::attach(uintptr_t irq)
{
return vector_t::table[irq - -1/*SysTick_IRQn*/].attach(this);
}
_OPT_INLINE__ look::interrupt_t*
look::vector_t::attach(interrupt_t* intr)
{
interrupt_t*
old = interrupt;
interrupt
= intr;
return
old;
}
在vector_t类中找到table[], 从这几段代码看出在产生中断时就可以通过table[中断号].interrupt.isr/dsr来调用
对应中断的相关中断函数了,应为每个table[]中都用了interrupt *将其联系起来了,好了中断就讲到这
#ifndef __DOXYGEN__
union {
struct {
interrupt_t* interrupt;
uint16_t count;
uint8_t next;
};
uint64_t data;
};
#endif // __DOXYGEN__
static vector_t table[] __attribute__((aligned(4)));
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
下面是我写的代码,一个uart0_int_c:public interrupt_t类实现串口的一些功能,可以设置参数,也可以用默认设置
这些代码有些都是照着MO库来改写的,并在一个任务中实现了mmbox_t<T,SIZE>多信息邮箱,如果串口中断接收到数据,则通过
邮箱将数据送到一个任务函数中并通过串口发送出去,邮箱的get()函数在没有信息时会使当前任务进入阻塞状态,只有有信息时,才能
激活任务,并读取邮箱里的数据。
uart.h
/*****************************************
//
//
******************************************/
#ifndef _Uart_h_
#define _Uart_h_
#include"look.h"
/*---------------------------------------------------------------------------------------------------------*/
/* DATA BIT */
/*---------------------------------------------------------------------------------------------------------*/
typedef enum
{
DRVUART_DATABITS_5 = 0x0,
DRVUART_DATABITS_6 = 0x1,
DRVUART_DATABITS_7 = 0x2,
DRVUART_DATABITS_8 = 0x3
} DATABITS_SET;
/*---------------------------------------------------------------------------------------------------------*/
/* PARITY Setting */
/*---------------------------------------------------------------------------------------------------------*/
typedef enum
{
DRVUART_PARITY_NONE = 0x0,
DRVUART_PARITY_ODD = 0x1,
DRVUART_PARITY_EVEN = 0x3,
DRVUART_PARITY_MARK = 0x5,
DRVUART_PARITY_SPACE = 0x7
} PARITY_SET;
/*---------------------------------------------------------------------------------------------------------*/
/* STOP BIT */
/*---------------------------------------------------------------------------------------------------------*/
typedef enum
{
DRVUART_STOPBITS_1 = 0x0,
DRVUART_STOPBITS_1_5 = 0x1,
DRVUART_STOPBITS_2 = 0x1
} STOPBITS_SET;
/*---------------------------------------------------------------------------------------------------------*/
/* FIFO Select */
/*---------------------------------------------------------------------------------------------------------*/
typedef enum
{
DRVUART_FIFO_1BYTES = 0x0,
DRVUART_FIFO_4BYTES = 0x1,
DRVUART_FIFO_8BYTES = 0x2,
DRVUART_FIFO_14BYTES = 0x3,
DRVUART_FIFO_30BYTES = 0x4,
DRVUART_FIFO_46BYTES = 0x5,
DRVUART_FIFO_62BYTES = 0x6
}FIFO_SET;
/*****************************************
//串口中断类
*****************************************/
class uart0_int_c :public interrupt_t{
public:
uart0_int_c(uint32_t u32Bandrate = 9600 ,PARITY_SET u8cParity=DRVUART_PARITY_NONE,\
STOPBITS_SET u8cStopBits=DRVUART_STOPBITS_1,DATABITS_SET u8cDataBits=DRVUART_DATABITS_8,\
FIFO_SET u8cRxTriggerLevel= DRVUART_FIFO_1BYTES);
void Uart0Close();
void Uart0RxEnableInt();//接收中断使能
void Uart0RxDisableInt();//接受中断失效
uint8_t Wstr(const char *);
uint8_t Write(uint32_t *,uint32_t);//发送数据
uint8_t Read(uint32_t * ,uint32_t);//读接收的数据
protected:
bool isr(int vector);
void dsr(int vector,uintptr_t count);
private:
void BaudRateSet(uint32_t clk, uint32_t baudRate);
};
#endif
uart.cpp串口代码
#include <NUC1xx.h>
#include"NUC1xxM051Seriescfg.h"
#include"LOOK_config.h"
#include"Uart.h"
//构造函数,并可以设置波特率,校验,数据位,停止位,UART_FIFO
uart0_int_c::uart0_int_c(uint32_t u32Bandrate ,PARITY_SET u8cParity,\
STOPBITS_SET u8cStopBits,DATABITS_SET u8cDataBits,\
FIFO_SET u8cRxTriggerLevel){
//将管脚设置为UART0模式
SYSs.GPBMFP.Bits.UART0_RX=1;
SYSs.GPBMFP.Bits.UART0_TX=1;
SYSs.GPBMFP.Bits.UART0_nRTS_nWRL=1;
SYSs.GPBMFP.Bits.UART0_nCTS_nWRH=1; //SYSs.GPBMFP.Regs|=0x0f;
/* Reset IP */
SYSs.IPRSTC2.Bits.UART0_RST = 1;
SYSs.IPRSTC2.Bits.UART0_RST = 0;
/* Enable UART0 clock */
SYSCLKs.APBCLK.Bits.UART0_EN=1;
UART0s.FCR.Bits.TFR =1;//TX/RX软复位
UART0s.FCR.Bits.RFR =1;
/* Set Rx Trigger Level */
UART0s.FCR.Bits.RFITL = u8cRxTriggerLevel;
/* Set Parity & Data bits & Stop bits */
UART0s.LCR.Bits.SPE =(u8cParity&0x4)?1:0;
UART0s.LCR.Bits.EPE =(u8cParity&0x2)?1:0;
UART0s.LCR.Bits.PBE =(u8cParity&0x1)?1:0;
UART0s.LCR.Bits.WLS =u8cDataBits;
UART0s.LCR.Bits.NSB =DRVUART_STOPBITS_1;
/* Set Time-Out */
UART0s.TOR.Bits.TOIC =0x7f;
//设置UART时钟为外部12M时钟
SYSCLKs.CLKSEL1.Bits.UART_S = 0;
BaudRateSet(F_CPU,u32Bandrate);//设置波特率
}
//关闭UART0串口
void uart0_int_c::Uart0Close()
{
while(UART0s.FSR.Bits.TE_FLAG);
SYSCLKs.APBCLK.Bits.UART0_EN = 0;
vector_t::disable(UART0_IRQn);
}
//使能UART0接收中断
void uart0_int_c::Uart0RxEnableInt()
{
UART0s.IER.Bits.RDA_IEN=1; //使能中断
attach(UART0_IRQn);
vector_t::enable(UART0_IRQn);
}
//失效
void uart0_int_c::Uart0RxDisableInt()
{
UART0s.IER.Bits.RDA_IEN=0;
vector_t::disable(UART0_IRQn);
}
uint8_t uart0_int_c::Wstr(const char *wstrbuf)
{
uint32_t u32delayno=0;
do{
u32delayno = 0;
UART0s.DATA.Regs=*wstrbuf++;
while (UART0s.FSR.Bits.TE_FLAG !=1) /* Wait Tx empty and Time-out manner */
{
u32delayno++;
if ( u32delayno >= 0x1000)
return 0;
}
}while(*wstrbuf!='\0');
return 1;
}
//发送数据
uint8_t uart0_int_c::Write(uint32_t *pu32TxBuf, uint32_t u32WriteBytes)
{
uint32_t u32Count, u32delayno;
for (u32Count=0; u32Count<u32WriteBytes; u32Count++)
{
u32delayno = 0;
while (UART0s.FSR.Bits.TE_FLAG !=1) /* Wait Tx empty and Time-out manner */
{
u32delayno++;
if ( u32delayno >= 0x1000)
return 0;
}
UART0s.DATA.Regs = pu32TxBuf[u32Count]; /* Send UART Data from buffer */
}
return 1;
}
//读数据
uint8_t uart0_int_c::Read(uint32_t *pu32RxBuf, uint32_t u32ReadBytes)
{
uint32_t u32Count, u32delayno;
for (u32Count=0; u32Count < u32ReadBytes; u32Count++)
{
u32delayno = 0;
while (UART0s.FSR.Bits.RX_EMPTY ==1) /* Check RX empty => failed */
{
u32delayno++;
if ( u32delayno >= 0x1000 )
return 0;
}
pu32RxBuf[u32Count] = UART0s.DATA.Regs; /* Get Data from UART RX */
}
return 1;
}
//M0库中的波特率设置函数
void uart0_int_c::BaudRateSet(uint32_t clk, uint32_t baudRate)
{
int32_t tmp;
int32_t div;
if(((clk / baudRate)%16)<3) /* Source Clock mod 16 <3 => Using Divider X =16 (MODE#0) */
{
UART0s.BAUD.Bits.DIV_X_EN = 0;
UART0s.BAUD.Bits.DIV_X_ONE = 0;
tmp = clk / baudRate/16 -2;
}
else /* Source Clock mod 16 >3 => Up 5% Error BaudRate */
{
UART0s.BAUD.Bits.DIV_X_EN = 1; /* Try to Set Divider X = 1 (MODE#2)*/
UART0s.BAUD.Bits.DIV_X_ONE = 1;
tmp = clk / baudRate -2;
if(tmp > 0xFFFF) /* If Divider > Range */
{
UART0s.BAUD.Bits.DIV_X_EN = 1; /* Try to Set Divider X up 10 (MODE#1) */
UART0s.BAUD.Bits.DIV_X_ONE = 0;
for(div = 8; div <16;div++)
{
if(((clk / baudRate)%(div+1))<3)
{
UART0s.BAUD.Bits.DIVIDER_X = div;
tmp = clk / baudRate / (div+1) -2;
break;
}
}
}
}
UART0s.BAUD.Bits.BRD = tmp;
}
main.cpp主文件
#include <NUC1xx.h>
#include"NUC1xxM051Seriescfg.h"
#include "main.h"
#include"M0Base.h"
#include"Uart.h"
/******************************************/
//声明对象
///////////////////////////////////////////
//key_int_c key;
led_ctl_c led1;
uart0_int_c uart0;
#ifdef LOOK_SCHEDULING_PRIORITY
instantiate::task<task1_main_t, LOOK_STACK_SIZE> task1_main(0);
instantiate::task<task2_uart0_c,LOOK_STACK_SIZE> task2_uart0(1);
#else
instantiate::task<task1_main_t, LOOK_STACK_SIZE> task1_main;
instantiate::task<task2_uart0_c,LOOK_STACK_SIZE> task2_uart0;
#endif
/*************************************
//task1任务类的任务函数
**************************************/
void task1_main_t::routine()
{
led_ctl_c led;
// TODO: 在此编写 task1_main_t 例程的内容
while (true) {
led.Led1to4();
scheduler.yield();
// TODO: 在此编写 task1_main_t 例程的内容
}
}
/***************************************
//
***************************************/
void task2_uart0_c::routine()
{
uart0.Uart0RxEnableInt(); //使能接受中断
while(true){
#ifdef _DEBUG_
uart0.Wstr("before uart_megs");
#endif
uint32_t msg=uart_megs.get();
uart0.Wstr("接收的内容:");
uart0.Write(&msg,1); //发送接收的数据
uart0.Wstr("\n");
}
}
/***************************************
*按键中断类成员函数
****************************************/
inline key_int_c::key_int_c()
{
attach(EINT0_IRQn); //将中断号和本对象挂钩
attach(EINT1_IRQn);
GPIOBs.IEN.Regs = (1 << Pin15) | (1 << Pin14); // 开启中断
vector_t::enable(EINT0_IRQn);//必须在有main.h的头文件中
vector_t::enable(EINT1_IRQn);
}
// Keyboard_t 中断服务例程
bool key_int_c::isr(int vector)
{
GPIOBs.ISRC.Regs = GPIOBs.ISRC.Regs; // 清中断 flag
return true;
}
// Keyboard_t 中断滞后服务例程
void key_int_c::dsr(int vector, uintptr_t count)
{
if (vector == EINT0_IRQn)
{
// led1.Led4to1();
}
else if (vector == EINT1_IRQn)
{
// led1.Led1to4();
}
}
/*********************************
//uart0类的成员函数
***********************************/
bool uart0_int_c::isr(int vector)
{
#ifdef _DEBUG_
uart0.Wstr("Into uart0 isr\n");
#endif
return true;
}
void uart0_int_c::dsr(int vector, uintptr_t count)
{
uint32_t buf=0;
if(UART0s.ISR.Bits.RDA_INT==1)
{
#ifdef _DEBUG_
uart0.Wstr("Into uart0 dsr\n");
#endif
// do{
buf=UART0s.DATA.Regs;
task2_uart0.uart_megs.do_tryput(buf); //读取接收的数据
// task2_uart0.uart_megs.do_tryput('a');
// }while(UART0s.ISR.Bits.RDA_IF!=0);
}
}
其他代码不贴了,要的大家看程序,希望老师、大叔和大家多多提提意见,好让我提高下
有问题也可以一起多多交流下 |