Ti的C28x系列的DSP(28069)使用经验,SCI与RS485(ADM2587EBRWZ)

版权声明:原创博客,不得用于商业用途 https://blog.csdn.net/weixin_39768579/article/details/82255557

本人使用SCI的通讯经历也不多,仅仅是用于DSP与威纶通公司的触摸屏进行过简单的通讯,通讯方式为RS485,通讯协议为ModbusRTU。

说到SCI,一开始我弄这个的时候,也不懂,网上看了很多资料,但也没有特别合适的,我现在公司的DSP的代码架构,都是一个主中断,一个主循环,一个1ms定时器中断,所以通讯函数,要么放主循环或1ms中断中运行,不会为SCI单独弄个中断,但我这边也不想用《手把手教你学DSP--基于TMS320X281x》上描述的简单SCI查询方式通讯,因为这种方法FIFO没有用,会造成对CPU资源的浪费。

所以我现在提的SCI通讯方式是基于FIFO的轮询方式,以这种方式来配置寄存器,从而形成的读写函数。但28069的SCI的FIFO只有4级,28377D的FIFO有16级。RS485是读写是不能够同时进行的,具体特点,可以百度,这跟RS232不相同。RS485的读写函数是基于ADM2587EBRWZ芯片而写,除了SCI的RX与TX引脚,还多了一个DIR引脚,DIR引脚为高,SCI能够发送数据,反之,读取数据。

代码:

  • SCI的初始化;
void InitScia(void)  // LSPCLK =  SYSCLKOUT/4  = 20Mhz
{
	SciaRegs.SCICCR.all = 0x07;	//1 stopbit,no parity,
                                //idle line mode,loopback test disable


	SciaRegs.SCIHBAUD = 0x10;	//20M  baud 9600   BBR = 0x103   
                                // BBR = LSPCLK/(波特率*8) - 1
	SciaRegs.SCILBAUD = 0x3;

	SciaRegs.SCICTL1.all = 0x0003;  // enable TX, RX, internal SCICLK,
    	                            // Disable RX ERR, SLEEP, TXWAKE
	SciaRegs.SCICTL2.all = 0;

	SciaRegs.SCIFFTX.all = 0xE040;


	SciaRegs.SCIFFRX.all = 0x2040;

	SciaRegs.SCIPRI.bit.SOFT = 1;	//Complete current receive/transmit 
                                    //sequence before stopping
	SciaRegs.SCIPRI.bit.FREE = 0;

	SciaRegs.SCICTL1.bit.SWRESET = 1;
}

void InitScib(void)
{
	ScibRegs.SCICCR.all = 0x07;	//1 stopbit,no parity,
                                //idle line mode,loopback test disable


	ScibRegs.SCIHBAUD = 0x10;	//20M  baud 9600   BBR = 0x103  
                                //BBR = LSPCLK/(波特率*8) - 1
	ScibRegs.SCILBAUD = 0x3;

	ScibRegs.SCICTL1.all = 0x0003;  // enable TX, RX, internal SCICLK,
								   // Disable RX ERR, SLEEP, TXWAKE
	ScibRegs.SCICTL2.all = 0;

	ScibRegs.SCIFFTX.all = 0xE040;

	ScibRegs.SCIFFRX.all = 0x2040;

	ScibRegs.SCIPRI.bit.SOFT = 1;	//Complete current receive/transmit
                                    // sequence before stopping
	ScibRegs.SCIPRI.bit.FREE = 0;

	ScibRegs.SCICTL1.bit.SWRESET = 1;
}


void InitScibGpio(void)
{
	EALLOW;

	GpioCtrlRegs.GPAPUD.bit.GPIO22 = 0;     // Enable pull-up for GPIO22 (SCITXDB)
	GpioCtrlRegs.GPAPUD.bit.GPIO23 = 0;     // Enable pull-up for GPIO23 (SCIRXDB)


	GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 3;   // Asynch qual for GPIO23 (SCIRXDB)

	GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 3;    // Configure GPIO22 for SCITXDB operation
	GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 3;    // Configure GPIO23 for SCIRXDB operation


	EDIS;
}
  • SCI的读写及复位函数;

复位函数:

void SciReset(Uchar dev)
{
	volatile struct SCI_REGS *p;

		switch(dev)
		{
			case Sci_a:
				p = &SciaRegs;
			break;
			case Sci_b:
				p = &ScibRegs;
			break;
			default:
				p = &SciaRegs;
			break;
		}

	if(	p->SCIRXST.bit.RXERROR || p->SCIRXST.bit.FE || 
        p->SCIRXST.bit.PE || p->SCIRXST.bit.OE )  
	{
		p->SCICTL1.bit.SWRESET = 0;

		DELAY_US(100);

		p->SCICTL1.bit.SWRESET = 1;
	}
}

写函数:


Uint16 WriteSci(Uchar dev,char *buf,Uint16 cnt)
{
	static Uint16 i,Num;
	volatile struct SCI_REGS *p;

	switch(dev)
	{
		case Sci_a:
			p = &SciaRegs;
		break;
		case Sci_b:
			p = &ScibRegs;
		break;
		default:
			p = &SciaRegs;
		break;
	}

	i=0;
	Num = cnt;

	SciReset_C1062(dev);

	while(p->SCIFFTX.bit.TXFFST != 0);

	p->SCICTL1.bit.TXWAKE = 1;
	p->SCITXBUF = 0xAA;

	while(i < Num)
	{
		while(p->SCIFFTX.bit.TXFFST >= 4);

		p->SCITXBUF = buf[i++];
	}

	return(i);
}

 

读函数:

读函数这里有个DELAY_US(3800),这个非常重要,没有这个延时RS485没法正常的读取数据,至于原理,暂时我也没完全搞清楚,应该是为了度过发送数据的而产生的低电平吧,因为DIR引脚为高时,ADM2587EBRWZ芯片的引脚会把SCI的Rx引脚拉低,如果这段时间SCIRX引脚读数据会读到错误的数据,因为SCI的Rx引脚的起始位认为是低电平,这个读函数完全时为了RS485而准备的,我也试过RS232,当使用RS232时,SCI的收发是互不干扰,就没有这个问题。

Uint16 ReadSci(Uchar dev,char *buf)
{
	static Uint16 i;
	volatile struct SCI_REGS *p;

	switch(dev)
	{
		case Sci_a:
			p = &SciaRegs;
		break;
		case Sci_b:
			p = &ScibRegs;
		break;
		default:
			p = &SciaRegs;
		break;
	}

	SciReset_C1062(dev);

	if(p->SCIFFRX.bit.RXFFST == 0)
	{
		return(0);
	}

	i = 0;

	do
	{
		while(p->SCIFFRX.bit.RXFFST != 0)
		{
			buf[i] = p->SCIRXBUF.bit.RXDT;

			i ++;
		}

		DELAY_US(3800);

	}while(p->SCIFFRX.bit.RXFFST  != 0);

	return(i);
}

忙函数:

void BusyWaitingSci(Uchar dev)
{
	volatile struct SCI_REGS *p;

	switch(dev)
	{
		case Sci_a:
			p = &SciaRegs;
		break;
		case Sci_b:
			p = &ScibRegs;
		break;
		default:
			p = &SciaRegs;
		break;
	}

	while(p->SCIFFTX.bit.TXFFST > 0);
}

波特率设置函数:

void SetBaudrateSci(Uchar dev,Uint32 baud)
{
	Uint32 rate;
	volatile struct SCI_REGS *p;

	switch(dev)
	{
		case Sci_a:
			p = &SciaRegs;
		break;
		case Sci_b:
			p = &ScibRegs;
		break;
		default:
			p = &SciaRegs;
		break;
	}
	rate = 20000000 / (baud*8) - 1;
	p->SCIHBAUD = rate >> 8;	//20M  baud 9600 2603
	p->SCILBAUD = rate & 0x0FF;
}
  • RS485函数;

写函数:

void Rs485Write(char *buf,Uint32 Baudrate,Uint16 cnt)
{
    float ByteDelay;

	ByteDelay = (1000000 / Baudrate ) * 11;

	RcvDisable();

	DELAY_US(10);

	ADM2587_Write(buf,cnt);

	ADM2587_BusyWaiting();

	DELAY_US(ByteDelay);

	RcvEnable();
}

读函数:

Uint16 Rs485Read(char *buf)
{
	RcvEnable();

	DELAY_US(10);

	return(ADM2587_Read(buf));
}

头文件:


#define ADM2587_Write(buf,cnt)		WriteSci(Sci_b,buf,cnt)
#define ADM2587_Read(buf)		ReadSci(Sci_b,buf)
#define ADM2587_BusyWaiting()		BusyWaitingSci(Sci_b)
#define ADM2587_BaudrateSet(baud)	SetBaudrateSci(Sci_b,baud)


#define RcvDisable()    GpioDataRegs.GPBSET.bit.GPIO50  = 1
#define RcvEnable()	    GpioDataRegs.GPBCLEAR.bit.GPIO50  = 1

猜你喜欢

转载自blog.csdn.net/weixin_39768579/article/details/82255557