This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28335: The data printed using the sci serial port is incomplete

Part Number: TMS320F28335
Other Parts Discussed in Thread: C2000WARE

The data printed using the sci serial port is incomplete.

I saw on some forums that it is related to the redirection of printf, where can I set the redirection? Is there a tutorial?

I use the "console" window to print everything fine, but switch back to the serial port print data is not complete.

--

Thanks & Regards

  • Hello,

    I assume a custom printf solution using SCI is being used here as mentioned in the "Using printf() to output to a user-defined device" section of the below article:

    https://dev.ti.com/tirex/explore/node?node=A__AIwt8bIK1yTVvzbnfYL0gg__ccs_devtools__FUz-xrs__LATEST

    I'll bring this thread to the attention of the C2000 experts for further assistance.

    Thanks

    ki

  • Hi Yale,

    Thanks for your question. Do you happen to be using the debugger mode when you are running this? When debugger is active, it can halt the transmission of data mid-stream so that could lead to incomplete data. Can you try to run without debugging and see if the issue persists?

    Regards,

    Vince

  • I do not understand the debugger mode, I use ccs10.0 software only after debug can I burn to dsp28335?

    If I'm wrong, please tell me how to turn off debug mode.

  • Hi Yale,

    The typical process is to

    1. load the code to the device (flash or RAM, but flash is permanent and stays between power cycles).

    2. In CCS, find the "disconnect" button in the top to disconnect the device from the debugger

    3. The code will now run freely without the debugger connected. You can observe the COM port terminal and see if it looks correct.

    Regards,

    Vince

  • Hi Toledo,

    I am the author of this question and thank you very much for your answer.

    I burned the code into flash as you asked and clicked the "disconnect" button in ccs10.1.0, but the data printed out from the serial port was still incomplete, and I tested it multiple times to make sure it didn't work out.

    My code did not make any changes, in the previous use can normally output all the characters, but after using the "console" window to print output again using the "sci" serial port there is a problem.

    The following figure shows the result printed using the ccs serial assistant.

    You can see that the data is incomplete and there are strange line breaks.

    If required, I am willing to provide my "SCI.c" and "SCI.h" files, as well as the "main.c" files that enable sci.

    By the way, does this issue have anything to do with the "printf" redirection?

    Your reply will be highly appreciated as soon as possible!

    Regards,

    Andy

  • Hi Andy,

    I think I see the miscommunication: are you expecting more decimal places? You are using the formatting incorrectly if that's the case.

    You have chose "0.2f". This means print only two decimal places for the float. That is why you're not getting more decimal places.

    Basically, the formatting you have chosen in printf is incorrect.

    For the strange line breaks (with space before the text), that's caused by the carriage return (\r) not being executed properly. Can you try re-arranging the order to "\n\r" instead of "\r\n"? I think what is happening is the printf data is sometimes overflowing the buffer. So you may need a delay between the printf statements (or make them one larger prinf statement).

    Regards,

    Vince

  • HI Toledo,

    Thank you for your answer.

    think I see the miscommunication: are you expecting more decimal places? You are using the formatting incorrectly if that's the case.

    You have chose "0.2f". This means print only two decimal places for the float. That is why you're not getting more decimal places.

    I don't want to get any more decimals, the figure above is to show you that the data is not printed completely, you will find that the "°" after "0.2f°" is not printed, in fact, no matter what character is put after "0.2f" can not be printed.

    For the strange line breaks (with space before the text), that's caused by the carriage return (\r) not being executed properly. Can you try re-arranging the order to "\n\r" instead of "\r\n"? I think what is happening is the printf data is sometimes overflowing the buffer. So you may need a delay between the printf statements (or make them one larger prinf statement).

    I tried replacing "\r\n" with "\n\r" but it didn't work

    I tried to change the main control from 28335 to 28035, but the problem was still not solved. I copied the complete code to another computer, but I could use the "sci" port to output data, which proves that there may be a problem in the configuration of ccs10.1.0 on my computer!

    So I want to uninstall ccs10.1.0 and replace it with ccs12.5. Do you think this might work?

    Can you provide TI's official "sci" usage code? Can you provide information about printf redirection?

    Also check out this link:CCS6中printf()的使用——TMS320F28335工程printf()的使用_ccs printf-CSDN博客

    As a dsp learner, I don't know where to put the nt fputc(int _c, register FILE *_fp) function.

    I really want your help. 

    sci.c file

    /*
     * sci.c
     *
     *  Created on: 2022年11月3日
     *      Author: 13739
     */
    #include "sci.h"
    #include "head.h"
    #include <stdio.h>
    #include <file.h>
    #include "DSP2803x_Project.h"
    
    
    Uart_Msg SCI_Msg={0, {0},0,0};
    
    //#define SYSCLK 60000000L
    
    //#################################################
    //串口接收缓存处理函数
    //-----------------------------------------------
    void handleRxFIFO()
    {
    	if(SCI_Msg.Mark_Para.Status_Bits.rFifoDataflag == 1 )
    	{
    		SCI_Msg.Mark_Para.Status_Bits.rFifoDataflag =0;
    		while(SCI_Msg.rxReadIndex != SCI_Msg.rxWriteIndex)
    		{
    			SCI_Msg.rxReadIndex=(++SCI_Msg.rxReadIndex)%(UartRxLEN);
    		}
    	}
    }
    
    
    //#################################################
    //串口接收中断函数
    //采用FIFO机制(缓存)
    //SCI_FIFO_LEN 定义为 1,最大为4
    //-----------------------------------------------
    interrupt void uartRx_isr(void)
    {
        SciaRegs.SCIFFRX.bit.RXFFINTCLR=1;      // Clear Interrupt flag
    	PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
    
    	if(SciaRegs.SCIFFRX.bit.RXFFOVF == 0)//接收FIFO未溢出
    	{
    		SCI_Msg.Mark_Para.Status_Bits.rFifoDataflag = 1;
    
    		//接收数据
    		while(SciaRegs.SCIFFRX.bit.RXFFST)
    		{
    			SCI_Msg.rxData[SCI_Msg.rxWriteIndex] = SciaRegs.SCIRXBUF.all;  //接受低八位数据
    			SCI_Msg.rxWriteIndex=(++SCI_Msg.rxWriteIndex)%(UartRxLEN);
    		}
    
    	}
    	else
    	{
    		//用户这里做串口硬件溢出的处理,可以完全读取出FIFO里的数据或者清空FIFO
    		//这里清空FIFO操作
    		SciaRegs.SCIFFRX.bit.RXFFOVRCLR=1;     // Clear HW Overflow flag
    		SciaRegs.SCIFFRX.bit.RXFIFORESET = 0;  //Write 0 to reset the FIFO pointer to zero, and hold in reset.
    		SciaRegs.SCIFFRX.bit.RXFIFORESET = 1;  //Re-enable receive FIFO operation
    	}
    }
    
    
    //#################################################
    //-----------------------------------------------
    //串口初始化:
    //115200  8N1
    // P21 框图介绍中断
    //-----------------------------------------------
    void SCI_Init(Uint32 baud)
    {
    //设置串口波特率
    	unsigned char scihbaud=0;
    	unsigned char scilbaud=0;
    	Uint16 scibaud=0;
    
    	scibaud=37500000/(8*baud)-1;
    	scihbaud=scibaud>>8;
    	scilbaud=scibaud&0xff;
    
    
    	EALLOW;
    	SysCtrlRegs.PCLKCR0.bit.SCIAENCLK = 1;   // SCI-A
    	EDIS;
    
    	InitSciaGpio();
    //SCI工作模式的设置
    	SciaRegs.SCICTL1.bit.SWRESET = 0;//sci 复位操作
     	SciaRegs.SCICCR.all =0x0007;   // 1 stop bit,  No loopback
                                       // No parity,8 char bits,
                                       // async mode, idle-line protocol
     									//1个停止位,无回环,无奇偶校验,8个字符位,异步模式,空闲线路协议
    // baud = LSPCLK/8/((BRR+1)
    // baud @LSPCLK = 15MHz (60 MHz SYSCLK)
    //	SciaRegs.SCIHBAUD    =0x0000;
    //  SciaRegs.SCILBAUD    =15;      //0xC2-->9600; 15-->115200(117187); 14-->128000(125000);3-->500000(468750)
        SciaRegs.SCIHBAUD    =scihbaud;
    
    
        //此处有些不同
     	SciaRegs.SCILBAUD    =scilbaud;
    
        SciaRegs.SCICTL1.bit.SWRESET = 1;     // Relinquish SCI from Reset
    
        SciaRegs.SCIFFTX.bit.SCIRST=1;
    	SciaRegs.SCIFFRX.bit.RXFFIL  = SCI_FIFO_LEN;  //设置FIFO深度=1
    	SciaRegs.SCICTL1.bit.TXENA = 1;       //使能发送
    	SciaRegs.SCICTL1.bit.RXENA = 1;       //使能接收
    
    //	SciaRegs.SCICTL2.bit.TXINTENA =1;
    //	SciaRegs.SCICTL2.bit.RXBKINTENA =1;
    //  SciaRegs.SCIFFTX.bit.TXFFIENA = 0; //禁止发送中断使能
    
    	//中断配置步骤-----1
    	SciaRegs.SCIFFTX.bit.SCIFFENA = 1; //使能FIFO中断
    	SciaRegs.SCIFFRX.bit.RXFFIENA=1;
    
    	//中断配置步骤-----2
    	EALLOW;
    	PieVectTable.SCIRXINTA = &uartRx_isr;
    	EDIS;
    
    	//中断配置步骤-----3
    	PieCtrlRegs.PIEIER9.bit.INTx1 = 1;
    
    	//中断配置步骤-----4
    	IER |= M_INT9;
    
    	SciaRegs.SCIFFCT.all=0x00;
    
    	SciaRegs.SCIFFTX.bit.TXFIFOXRESET=1;
    	SciaRegs.SCIFFRX.bit.RXFIFORESET=1;
    	printf("\r\nSCI口 init...OK");//2023.7.13  zs  加
    }
    
    //#################################################
    //-----------------------------------------------
    //发送一个字节
    //-----------------------------------------------
    void scia_xmit(int a)
    {
    	Uint32 WaitTimer = 0;
    
    	//while (SciaRegs.SCIFFTX.bit.TXFFST != 0)
    	while(SciaRegs.SCICTL2.bit.TXEMPTY != 1) //发送缓存寄存寄如果不为空,则等待执行
    											//waitTimer 时间
    	{
    		WaitTimer++;
    		if(WaitTimer > TIMEROUTSCI)break;
    	}
    	if(WaitTimer <= TIMEROUTSCI)
    		SciaRegs.SCITXBUF=a;
    }
    
    //#################################################
    //-----------------------------------------------
    //发送字符串(待理解)
    //Enter,带回车换行次数
    //-----------------------------------------------
    void sciPutString(char Enter1,char *s, char Enter2)
    {
    	char i;
    
    	for(i=0;i<Enter1;i++)
    	{
    		scia_xmit(0x0D);
    		scia_xmit(0x0A);
    	}
    
    	while(*s!=0)
    	{
    		scia_xmit(*(s++));
    	}
    
    	for(i=0;i<Enter2;i++)
    	{
    		scia_xmit(0x0D);
    		scia_xmit(0x0A);
    	}
    }
    
    
    //-------------------------------以下都为 标准 printf函数连接--------------------------------------------------------------
    //#################################################
    //-----------------------------------------------
    //Printf 函数连接
    //-----------------------------------------------
    void open_uart_debug (void)
    {
    	int status=0;
    	status = add_device("uart", _MSA, my_open, my_close, my_read, my_write, my_lseek, my_unlink, my_rename);
    	if (status == 0) {
    		freopen("uart:", "w", stdout);		// open uart and redirect stdout to UART
    		setvbuf(stdout, NULL, _IONBF, 0); 	// disable buffering for stdout
    	}
    }
    
    int my_open(const char *path, unsigned flags, int fno)
    {
    	//scia_fifo_init();
    	//scia_echoback_init();
    	path = path;
    	flags = flags;
    	fno = fno;
    	return 0;
    }
    
    int my_close(int fno)
    {
    	fno =fno;
    	return 0;
    }
    
    int my_read(int fno, char *buffer, unsigned count)
    {
    	fno = fno;
    	buffer = buffer;
    	count = count;
    	return 0;
    }
    
    int my_write(int fno, const char *buffer, unsigned count)
    {
    	int i=0;
    	fno = fno;
    
    	while(count-- > 0) {
    		scia_xmit(buffer[i++]);
    	}
    	return count;
    }
    
    off_t my_lseek(int fno, off_t offset, int origin)
    {
    	fno = fno; offset = offset; origin = origin;
    	return 0;
    }
    
    int my_unlink(const char *path)
    {
    	path = path;
    	return 0;
    }
    
    int my_rename(const char *old_name, const char *new_name)
    {
    	old_name = old_name;
    	new_name = new_name;
    	return 0;
    }
    
    //****************************
    // No More
    //****************************
    
    

    sci.h file

    /*
     * sci.h
    
     */
    
    #ifndef APP_SCI_SCI_H_
    #define APP_SCI_SCI_H_
    
    #include "DSP2803x_Device.h"     // DSP2833x 头文件
    #include "DSP2803x_Examples.h"   // DSP2833x 例子相关头文件
    #include <stdio.h>
    #include <file.h>
    
    
    #define SCIBaudRate   115200L
    #define TIMEROUTSCI (Uint32)10*(SYSCLK/SCIBaudRate) //估算的等待超时时间,请根据实际修改
    
    
    #define SCI_FIFO_LEN  1 //定义DSP串口FIFO深度
    
    #define UartRxLEN 8  //接收缓存长度
    #define UartTxLEN 1  //发送缓存长度
    
    typedef struct Uart_Type{
    	union
    	  {
    	    Uint16 All;
    	    struct{
    	            Uint16  UartRevFlag        :1;  //接收到数据标志
    	            Uint16  rFifoDataflag      :1;  //接收内存非空
    	    		}Status_Bits;
    	  	}Mark_Para;
    	  	Uint16 rxData[UartRxLEN];				//接收缓存
    	Uint16 rxReadIndex;                         //接收FIFO写入索引:写入数据的长度?
    	Uint16 rxWriteIndex;                        //接收FIFO读出索引:读出数据的长度?
    }
    Uart_Msg;
    
    extern Uart_Msg SCI_Msg;
    
    //函数声明
    void handleRxFIFO(void);
    void SCI_Init(Uint32 baud);
    void usart1_send_byte(int a);
    void usart1_send_char(unsigned char * msg);
    void open_uart_debug (void);
    int printf(const char* str, ...);
    
    
    //标准 printf函数连接
    int my_open(const char *path, unsigned flags, int fno);
    int my_close(int fno);
    int my_read(int fno, char *buffer, unsigned count);
    int my_write(int fno, const char *buffer, unsigned count);
    off_t my_lseek(int fno, off_t offset, int origin);
    int my_unlink(const char *path);
    int my_rename(const char *old_name, const char *new_name);
    
    
    
    #endif /* APP_SCI_SCI_H_ */
    

    main.c file: The "sci" code appears only in main.c

    /*
     * main.c
     *
     *
     */
    
    
    #include "DSP2803x_Device.h"     // DSP2833x Headerfile Include File
    #include "DSP2803x_Examples.h"   // DSP2833x Examples Include File
    #include "DSP2803x_Project.h"
    #include "math.h"
    #include "IQmathLib.h"
    #include "head.h"
    #include "stdio.h"
    #include "bmp280.h"
    #include "leds.h"
    
    
    extern Uint16 RamfuncsLoadSize;
    
    float pitch,roll,yaw; 		//欧拉角
    
    short aacx,aacy,aacz;		//加速度传感器原始数据
    short gyrox,gyroy,gyroz;	//陀螺仪原始数据
    short magx,magy,magz;		//磁力计原始数据
    short temp;				    //温度
    
    
    
    
    void main()
    {
    	//long BMP_Pressure;
    //	double	BMP_Pressure,BMP_Temperature;//压力和温度
        //double  BMP_Pressure;
    	InitSysCtrl();//系统时钟初始化,默认已开启F28335所有外设时钟
    
    	InitGpio();
    
    	DINT;
    
    	InitPieCtrl();
    
    	IER = 0x0000;
    	IFR = 0x0000;
    
    	InitPieVectTable();
    
    	//复制对时间敏感代码和FLASH配置代码到RAM中
    	// 包括FLASH初始化函数 InitFlash();
    	// 链接后将产生 RamfuncsLoadStart, RamfuncsLoadEnd, 和RamfuncsRunStart
    	// 参数. 请参考 F28335.cmd 文件
    	memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (Uint32)&RamfuncsLoadSize);
    	// 调用FLASH初始化函数来设置flash等待状态
    	// 这个函数必须在RAM中运行
    	InitFlash();
    
    
    	////////////////////////////////////////////
    	//   SCI口初始化
    	////////////////////////////////////////////
    	SCI_Init(115200);//波特率115200(117187)
    	open_uart_debug();//串口硬件连接到printf标准函数
    	printf("\r\n\r\n\r\nDSP is Ready");
    	printf("\r\nSCI口 init...OK");
    
    	///////////////////////////////////////////////
    	// GPIO口(LED)初始化
    	///////////////////////////////////////////////
    	LED_Init();
    	printf("\r\nLEDGPIO口...OK");
    
    	///////////////////////////////////////////
    	// I2C口初始化(MPU6050模块初始化)
    	///////////////////////////////////////////
    //	MPU_Init();			  //初始化MPU9250!
    //	printf("\r\nMPU_Init init...OK");
    
    	//中断配置步骤-----5
    	PieCtrlRegs.PIECTRL.bit.ENPIE = 1;    // Enable the PIE block
    	EINT;                                 // Enable Global interrupt INTM
    	ERTM;//请参看 使用须知 文件夹下的   分享--ERTM、DRTM 在DSP编程中的作用.pdf
    
    
    	//mpu_dmp检测函数
    	//注意:杜邦线接短点,MPU6050放平
    		    while(1)  //初始化成功,则返回0,不运行下面的代码
    		    //while(mpu_dmp_init())  //初始化成功,则返回0,不运行下面的代码
    		 	{
    		    	//error = mpu_dmp_init();
    		    			printf("ERROR:%d\r\n",mpu_dmp_init());
    		    			switch (mpu_dmp_init())
    		    			{
    		    				case 0:printf("DMP库初始化正常\r\n");break;
    		    				case 1:printf("设置传感器库失败\r\n");break;
    		    				case 2:printf("设置FIFO库失败\r\n");break;
    		    				case 3:printf("设置采样率失败\r\n");break;
    		    				case 4:printf("加载DMP固件失败\r\n");break;
    		    				case 5:printf("设置陀螺仪方向失败\r\n");break;
    		    				case 6:printf("设置DMP功能失败\r\n");break;
    		    				case 7:printf("设置DMP输出速率失败\r\n");break;
    		    				case 8:printf("自检失败\r\n");break;
    		    				case 9:printf("使能DMP失败\r\n");break;
    		    				case 10:printf("初始化MPU9250失败\r\n");break;
    		    				default:printf("未知错误\r\n");break;
    		    			}
    		    			if(mpu_dmp_init() == 0)break;
    	            printf("\r\nmpu_dmp检测不正常!");
    				DELAY_US(500*1000);
    				//LED2_TOGGLE;      //LED灯D3闪烁,mpu_dmp检测不正常!
    			}
    			printf("\r\n实现功能:");
    			printf("\r\n发送加速度传感器数据aaci");
    			printf("\r\n发送陀螺仪值gyroi");
    			printf("\r\n发送欧拉角roll、pitch、yaw");
    
    	//陀螺仪采样率:            4~1000(Hz);目前是50Hz
    	//roll:横滚角.单位0.01度。  (-90.0°, +90.0°)
    	//pitch:俯仰角.单位 0.01度。(-180.0°, +180.0°)
    	//yaw:航向角.单位为0.1度    (-180.0°, +180.0°)
    	//温度值:扩大了100倍
    	//aaci加速度传感器原始数据:±2g
    	//gyroi陀螺仪原始数据:      ±2000dps
    
    			while(1)
    			{
    				//MPU_Read();
    				//DATA_Report();
    
    				if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0)      //获取欧拉角
    				{
    					temp=MPU_Get_Temperature();	                //获取温度值
    					MPU_Get_Accelerometer(&aacx,&aacy,&aacz);	//获取加速度传感器数据
    					MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);	//获取陀螺仪数据
    					MPU_Get_Magnetometer(&magx,&magy,&magz);	//获取磁力计数据
    
    					printf("\n\r Pitch:%0.2f°;Roll:%0.2f°;Yaw:%0.2f°",pitch,roll,yaw);    //显示欧拉角
    					printf("\n\r temp:%0.4d℃",temp);                                             //显示温度
    					//printf("\r\n aacx :%0.4d  ;aacy : %0.4d  ;aacz :%0.4d  ",aacx,aacy,aacz);    //显示加速度传感器原始数据
    					//printf("\r\n gyrox:%0.4d  ;gyroy: %0.4d  ;gyroz:%0.4d  ",gyrox,gyroy,gyroz); //显示陀螺仪原始数据
    					//printf("\r\n magx :%0.4d  ;magy: %0.4d   ;magz :%0.4d  ",magx,magy,magz); //显示陀螺仪原始数据
    					printf("\n\r");
    					DELAY_US(200*1000);
    
    				}
    
    				DELAY_US(200*1000);
    
    			} //end while(1)
    
    
    
    }
    
    

    Regards,

    Andy

  • Hi Andy,

    Can you try to replace the semicolon ";" with " - " dashes instead? I think sometimes the semicolon can be interpreted by the terminal as a end of line character and I'm wondering if that's happening here.

    So I want to uninstall ccs10.1.0 and replace it with ccs12.5. Do you think this might work?

    Good catch, the other system may work because possibly the COMM terminal in the older CCS is truncating the text when it sees a semicolon. I would definitely start with trying upgrade to CCS12.5 first and see if that solves the issue. Also, there are known bugs in the CCS10.1.0 installation, so upgrading would help fix those.

    Can you provide TI's official "sci" usage code? Can you provide information about printf redirection?

    For the above question, we actually have an example in the latest C2000Ware that does exactly what you're looking for, but for another device (f2838x and newer devices). Example is called: "sci_ex4_stdout_redirect.c"

    That should help a lot with what you're trying to accomplish.

    Regards,

    Vince