TMS320F28XX问题讨论贴,我会尽量回答大家提出的问题
我对28XX系列比较熟悉,大家有问题可以跟帖讨论,我每天晚上抽空回复当然,我不是万能的,尽我所能帮助大家,互相提高 楼上:
你好
F2808M0,M1 SARAMS;L0,L1,H0 SARAMS;BootRom;Flash,OTP,这些存储器都怎么用?
映射的物理地址是固定的么?如果是固定的,那么它们各自映射空间是什么?
如果程序中开辟了一块数据表,和一段连续的全局变量应该放到哪个存储器空间?
如果想把部分程序代码在运行时由flash加载到RAM,该怎么做?
谢谢大侠不吝赐教 怎么没人顶啊 难得有楼主这样的好人呢。 关于qionggui84的问题
F2808M0,M1 SARAMS;L0,L1,H0 SARAMS;BootRom;Flash,OTP,这些存储器都怎么用?
M1 SARAMS;L0,L1,H0 SARAMS;这些是RAM可以用来放程序和数据
BootRom;Flash,OTP这些只能放程序代码
映射的物理地址是固定的,各自映射空间请查看2808的datasheet
如果程序中开辟了一块数据表,和一段连续的全局变量应该放到哪个存储器空间?
一般变量放到RAM空间,常量数据表可以放到程序空间
如果想把部分程序代码在运行时由flash加载到RAM,该怎么做?
这个建议看一下2808例程里的FLASH示例
简单来说需要在两个地方进行设置
1:CMD文件中需要配置
ramfuncs : LOAD = FLASHD,
RUN = RAML0,
LOAD_START(_RamfuncsLoadStart),
LOAD_END(_RamfuncsLoadEnd),
RUN_START(_RamfuncsRunStart),
PAGE = 0
2:main函数里要调用MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);并初始化FLASH
我说的可能不太清楚,不明白可以再讨论 请教一下只要使能中断的话PIEVECTORTABLE和PIECORTROL这两个和PIE中断相关的内容是不是必须要初始化呢?因为我看很多的例程仅仅初始化vectortable这个中断向量表,而没有运行初始化piecontrol. PIEVECTORTABLE和PIECORTROL都要初始化
如果把PIEVECTORTABLE比做酒店的房间,那么PIECORTROL就是每个房间的钥匙,如果一个人想住酒店,那么他必须知道房间号(初始化vectortable),还要有房间钥匙(初始化piecontrol) 请问F2812的SCI模块,使用他的增强功能FIFO模块发送的时候,假如打开了FIFO发送级别匹配,怎么会总是进入中断呢,中断函数里面我已经写了清除FIFO发送级别中断标志了呀,可是观察寄存器,发现根本没有清除掉。
相应代码如下:
初始化SCIA模块部分
// Config SCIA module
SCIFFTXA= 0x0000; // reset transmit chanel
SCIFFRXA= 0x0000; // reset transmit chanel
SCICCRA = 0x07; /* 1 stop bit, No loopback, No parity, 8 char bits, async mode, idle-line protocol */
SCICTL1A= 0x03; /* enable TX, RX, internal SCICLK, Disable RX ERR, SLEEP, TXWAKE */
SCICTL2A= 0x00;
SCIHBAUDA = SCIABAUDH;
SCILBAUDA = SCIABAUDL; // 波特率115200
SCICTL1A= 0x23; // Restar sci, enable Recieve and Transmit
SCIFFTXA= 0xC02F; // Enable TX interrupt,enable TX FIFO, Triger level set to 16
SCIFFRXA= 0x0026; // Enable RX interrupt,enable RX FIFO, Triger Level set to 5
SCIFFCTA= 0x0002; // disable Auto Baud rate check, Delay 2 baudclock period
SCIPRIA = 0x08;
SCIFFTXA |= BIT13;
SCIFFRXA |= BIT13;
SCI发送中断处理函数部分
interrupt void SciaTxIsr(void)
{
PerformSciaTx();//这里只是处理数据部分,不涉及寄存器。
SCIFFTXA |= BIT6; // Clear interrupt flag(就是这里,进入发送中断后执行完这一句,观察SCIFFTXA 寄存器,发现根本没有清除掉bit7的TXFIFO中断标志,导致重复进入发送中断,困惑。)
PIEACK |= PIEACK_GROUP9; // Acknowledge PIE group 9 int
EINT;
return;
}
假如我想用TXFIFO的话,例如一次发16个字节,应该怎么配置SCIFFTXA寄存器呢?
用TXFIFO的话,可以不用一个字节一个字节等待发送完毕,一次性写入16个字节就可以啦,这样理解对吧?
期待楼主的解惑,先行谢过啦!
谢谢 LZ辛苦了,无私的人, 我贴一个2808的TX FIFO例子你看一下,其实TI提供了很全的例子,所以你先看一下TI的代码,然后修改一下就OK
interrupt void sciaTxFifoIsr(void)
{
Uint16 i;
for(i=0; i< 8; i++)
{
SciaRegs.SCITXBUF=sdataA; // Send data
}
for(i=0; i< 8; i++) //Increment send data for next cycle
{
sdataA = (sdataA+1) & 0x00FF;
}
SciaRegs.SCIFFTX.bit.TXFFINTCLR=1; // Clear SCI Interrupt flag
PieCtrlRegs.PIEACK.all|=0x100; // Issue PIE ACK
}
interrupt void sciaRxFifoIsr(void)
{
Uint16 i;
for(i=0;i<8;i++)
{
rdataA=SciaRegs.SCIRXBUF.all; // Read data
}
for(i=0;i<8;i++) // Check received data
{
if(rdataA != ( (rdata_pointA+i) & 0x00FF) ) error();
}
rdata_pointA = (rdata_pointA+1) & 0x00FF;
SciaRegs.SCIFFRX.bit.RXFFOVRCLR=1; // Clear Overflow flag
SciaRegs.SCIFFRX.bit.RXFFINTCLR=1; // Clear Interrupt flag
PieCtrlRegs.PIEACK.all|=0x100; // Issue PIE ack
}
void scia_fifo_init()
{
SciaRegs.SCICCR.all =0x0007; // 1 stop bit,No loopback
// No parity,8 char bits,
// async mode, idle-line protocol
SciaRegs.SCICTL1.all =0x0003;// enable TX, RX, internal SCICLK,
// Disable RX ERR, SLEEP, TXWAKE
SciaRegs.SCICTL2.bit.TXINTENA =1;
SciaRegs.SCICTL2.bit.RXBKINTENA =1;
SciaRegs.SCIHBAUD = 0x0000;
SciaRegs.SCILBAUD = SCI_PRD;
SciaRegs.SCICCR.bit.LOOPBKENA =1; // Enable loop back
SciaRegs.SCIFFTX.all=0xC028;
SciaRegs.SCIFFRX.all=0x0028;
SciaRegs.SCIFFCT.all=0x00;
SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset
SciaRegs.SCIFFTX.bit.TXFIFOXRESET=1;
SciaRegs.SCIFFRX.bit.RXFIFORESET=1;
}
假如我想用TXFIFO的话,例如一次发16个字节,应该怎么配置SCIFFTXA寄存器呢?
怎么配置,这个看书,看datasheet都可以得到答案,我就不帮你查书了
用TXFIFO的话,可以不用一个字节一个字节等待发送完毕,一次性写入16个字节就可以啦,这样理解对吧?
你理解的对,这样可以减少中断次数,提高效率 首先万分感谢楼主的热心解答!!!
可是我的问题还是没有解决。SCIA模块其他的寄存器都没有什么问题,我也会配置。
就是这个SCIFFTXA寄存器,工作状态和TI的手册描述的不一样呀!
现在问题的核心在于使能TXFIFO后,执行SCIFFTXA |= BIT6;
调试程序,下断点观察SCIFFTXA 寄存器执行这句后,发现根本没有清除掉bit7的TXFIFO中断标志,导致重复进入发送中断。
可数据手册里面写的很清楚,想要清除TXFIFO发送级别匹配中断的FLAG(BIT7),就是通过向BIT6写1实现清零。
可我试过很多次了,向BIT6写1之后,BIT7的TXFIFO发送中断标志位根本没有清除,仍然保持为1.
无奈了 楼上用TI的scia_loopback_interrupts例子试一下可好?如果TI的原版例子也有问题,那么我晚上可以实际测试一下。 TI的2812外设例程ourdev_436636.zip(文件大小:812K) (原文件名:sprc097.zip) 先感谢楼主,在说明调试过程。谢谢楼主!!!
TI的例程也有问题,我把开发板的串口A连接到了电脑,用串口调试助手观察收到的数据,也发现了一些不理解的现象。
源代码修改了下面一句,重新定义串口通讯的波特率,以便于和上位机通讯
#define SCI_FREQ 115200(源代码为#define SCI_FREQ 100E3,但这个波特率无法和上位机通讯,所以修改了)
例程一开始运行,就不停的发送数据,在发送数据的sciaTxFifoIsr()中下断点,断点处语句为
SciaRegs.SCIFFTX.bit.TXINTCLR=1; // Clear SCI Interrupt flag
(以下简称的执行前,执行后,都是说的执行这条语句前和执行这条语句后。)
查看执行这条语句前后SCIFFTX寄存器的内容变化如下。
1.第一次进入中断,执行前0xE7A8,执行后0xE7A8,寄存器内容无变化(注意,BIT7没有被清零)。上位机的串口调试助手收到0个数据。
2.第二次进入中断,执行前0xEFA8,执行后0xEF28,寄存器内容有变化(注意,BIT7被清零了)。上位机的串口调试助手收到0个数据
3.第三次进入中断,执行前0xF0A8,执行后0xF028,寄存器内容有变化(注意,BIT7被清零了)。上位机的串口调试助手收到7个数据,分别为00 01 02 03 04 05 06。
4.第四次进入中断,执行前0xF0A8,执行后0xF028,寄存器内容有变化(注意,BIT7被清零了)。上位机的串口调试助手收到8个数据,分别为07 01 02 03 04 05 06 07。
以后循环3,4步的过程。
疑问来了,这样的FIFO发送,怎么用呢?
第一次进入中断,向SciaRegs.SCITXBUF中写入了8个数据,一个也没发出去。
第二次进入中断,再向SciaRegs.SCITXBUF中写入了8个数据,发出去了7个,发送的数据是上一次中断中写入的前7个数据00~06,少发了最后一个07。
第三次进入中断,终于正常了,SciaRegs.SCITXBUF中写入了8个数据,发出去了8个,但是发送的数据,是上一次8个数据的最后一个07,和这一次循环的01~07),BIT7的中断标志也可以正常清零了。
可是和我理解的向SciaRegs.SCITXBUF中写入了8个数据,就发8个数据,完全不一样呀。 12楼iceyfire
你好;
我也发现类似的问题;
调试RXFIFO时,产生问题可以解释:当ScibRegs.SCIFFRX.bit.RXFFIL = 0x06;PC机发送字节数为6时,正常接收到全部,发送字节数4 ,不产生中断,然后PC机再发送2个字节,这时产生中断,如果PC机发送8个字节,产生中断,不过只接受前六个字节;
但是在调试TXFIFO时,产生问题就无法解释了,和12楼发现问题类似,期待高手解释; 第一次进入中断,向SciaRegs.SCITXBUF中写入了8个数据,一个也没发出去。
这个正常,写进FIFO并不意味着发出去了
第二次进入中断
此时第一次写的8个数据已经从FIFO里移出了,FIFO此时空,实际计算机收到7个数据,我理解为发送寄存器中还有一个
第三次及以后均正常了
**********************************
我做了个测试,就是第一次进中断后写8个数据到FIFO,以后中断就不写了,实际是可以收到0-7数据的,也就是说第二次进中断你就可以认为第一次写的8个数据已经成功发送出去了,实际也是这样的
因为DSP中断后,会将CPU挂起,所以第8个字节有可能在发送寄存器里,计算机暂时接收不到
如果是ARM就不会有这个问题了
注意点:使用FIFO时,发送中断是FIFO空中断; 楼主:
你好:
在看苏奎峰等编著《TMS320F2812原理与开发》这本书时,第114页介绍SCI FIFO发送(SCIFFTX)寄存器功能描述,当TXFFIL4~0大于或等于状态TXFFST4~0时,发送FIFO将产生中断;
是不是可以这样理解,如果我把TXFFIL设置为6时,只要一发送1个字节(符合TXFFIL4~0大于或等于状态TXFFST4~0条件)就产生中断,那是不是就起不到用FIFO的初衷(减少中断次数)? 15楼,你好
如果我把TXFFIL设置为6时,发送FIFO中数据个数小于或者等于6就会产生中断了,但是FIFO有16个那么多哦,所以相对于产生16次中断,产生6次中断还是减少了中断次数的,TXFFIL在复位后默认值为0,也就是FIFO为空时才中断
实际使用中,你根据需要设置TXFFIL值就可以了 28X的SCI FIFO和我最近使用的ARM的FIFO不太一样,ARM中可以设置FIFO的长度,也就是说可以只使用4个字节、8个字节或者其他长度的FIFO,FIFO空了就会中断。
但28X中,我理解是16个FIFO一直都可以使用,但是可以设置发送FIFO在还剩下多少个数据时产生中断,TI的文档对这个部分说明不是太详细,大家多实践吧 但是楼主你贴的TI的例程里面讲TXFFIL设置成8,那么如果我一次向FIFO里面写入8个数据的话,是不是每次都会产生中断呢? 还有想请教一下,是不是这8个字符会连续发送出去?在这8字符没有发送完成的过程中,还会产生发送中断吗? 天才杨威利
你有仿真器的哦,自己实践一下吧 谢谢楼主了,出去调试啦,现在手头没有仿真器。明天按楼主的思路调试一下,在看看结果。
楼主真是热心人,呵呵,谢谢 楼主:
谢谢楼主不吝赐教;
我在网上看了一些关于Modbus485协议的评论,说是先要制订一份Mosbus登记表,记录各个寄存器对应的地址,因为标准Modbus协议面向寄存器地址,可以把不同变量映射到Mosbus登记表记录的地址。想打听一下楼主有没有按照标准Modbus协议来编制通讯程序模块,或者框架。给初学者我指点一下。 MODBUS还是比较简单的,有个freemodbus的开源软件,可以找来看看
还有一个叫 modbus poll的软件,也很不错哦,我做的时候就是用这个软件测试
基础就是UART发送接受,就象你会开车,现在要你按照指定路线开,并不复杂的 谢谢楼主指点
我去看看 请教一下AD中的CONVnn中的nn代表什么意思呢?我知道他是选择要采样的引脚。CONV11=0X07表示转换在ADCINA7和ADCINB7(同步采样)。
因此我想请教一下CONV11中的11代表什么意思? 我在文件1.C中定义了一个位定义结构体
struct
{
unsigned acc:1;
unsigned dec:1;
unsigned stopmod:2;
unsigned dirsel:1;
unsigned dirfor:1;
unsigned save:1;
}runcon4_flag;
想在2.C操作这个变量,就在2.C顶头 extern struct runcon4_flag;
但是编译不通过;
提示:
"2.c", line 226: error: identifier "runcon4_flag" is undefined
然后 我保留 extern struct runcon4_flag;
删除在2.C引用runcon4_flag,再编译,就编译通过,不过警告“"Modbus.c", line 23: warning: a storage class may not be specified here”,我双击它,就跳转到 “extern struct runcon4_flag;”
请问大侠这是怎么回事啊, 26楼,这个你参考一下DSP28xx_Gpio.h中结构体的用法 25楼,请参考
TMS320x280x DSP
模数转换器(ADC)
参考指南
SPRU716.pdf 请教楼主DX下
我用2808,但现在可以调试,运行OK
但我下载到FLASH中,就不运行了`
只是个普通的LED程序,我参考模板写的 29楼
要将程序在FLASH中运行,需要注意
1.编译模式选release
2.必须初始化FLASH
//设置FLASH寄存器程序调入RAM中运行
MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
InitFlash();
关于FLASH中运行,可以参考TI例程中的FLASH示例 谢谢LZ回答
我是在release 中编译的,也
运行了 MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
InitFlash(); 两个函数
这两个函数直接用的原来模板的,是没有问题的
`奇怪哈~
对了,我用的板子应该是在楼主这买的,
就是那个 TMS320F2808开发板(买DSP开发板送仿真器)
我现在使用它的程序模板,自己建立了一个项目,把模板中的文件都加了进去
同样的main.c在模板环境下可以,可以烧到FLASH中运行
在我的项目中就只可以调试,
我基本上能修改都改了,应该和模板没什么区别了~
现在只是个简单的LED闪烁程序
麻烦DX给看一下~不胜感谢!
点击此处下载 ourdev_438034.rar(文件大小:385K) (原文件名:BLDC.rar) 那你用光盘里综合实验的工程做模板,在其基础上添加自己的代码吧 谢谢楼主回答~
我知道问题出那了
我少加了个 DSP280x_CodeStartBranch.asm 文件,没有这个文件,编译也不回出错~
奇怪哈,不知道这文件是做什么的?
楼主的板子不错,程序写的满好的~我现在就用的楼主的模板程序~呵呵~DSP不简单哈~ 感谢楼上的肯定
不过我个人认为,DSP并不难,难的是基于DSP的应用,不管是ARM、DSP、51或者其他CPU,从使用CPU的角度来说都差不多,道理也是相通的。就象从南京到上海,可以采用步行、自行车、汽车等等交通方式,但前提是你必须知道路线(对你的目标应用要熟悉),用何种交通方式,只是效率问题。
另,最近新增了12864图形LCD的程序,需要可以best2002@vip.sina.com索取,效果如下,控制器为SED1565兼容
http://cache.amobbs.com/bbs_upload782111/files_14/ourdev_438331.jpg
(原文件名:12864s.jpg) 各位老师,问下MODBUS通讯,(DSP做从机),上位机在给下位机发指令要求数据的时候,modbus协议中的寄存器地址是怎么定义的,下位机中开关量的地址是一个虚拟的吗,就是定义一个表示开关量的位变量,这个变量就是那个地址,不过是由编译器临时分配的吧,那是不是我们上位机的协议中这个寄存器地址是怎么回事呢,他和下位机的这个是怎么连接的呢 。
请教一下,谢谢! 在请教楼主下
CMD文件中的 .cinit : > FLASHA PAGE = 0
.pinit : > FLASHA, PAGE = 0
.text : > FLASHA PAGE = 0
codestart : > BEGIN PAGE = 0
.cinit : > FLASHA PAGE = 0
.pinit : > FLASHA, PAGE = 0
.text : > FLASHA PAGE = 0
codestart : > BEGIN PAGE = 0
ramfuncs : LOAD = FLASHD,
RUN = RAML0,
LOAD_START(_RamfuncsLoadStart),
LOAD_END(_RamfuncsLoadEnd),
RUN_START(_RamfuncsRunStart),
PAGE = 0 RUN = RAML0,
LOAD_START(_RamfuncsLoadStart),
LOAD_END(_RamfuncsLoadEnd),
RUN_START(_RamfuncsRunStart),
PAGE = 0
是把FLASH的程序烤到RAML0中运行
但我看RAML0只有4K,如果程序大过4K怎么办?
怎么让程序都在FLASH中运行?
这样修改可以不?
ramfuncs : > FLASHD, PAGE = 0
谢谢了` 先出差,回来再说^-^ RAM不够的话,可以换大块的RAM区
你定义了ramfuncs才需要执行COPY到RAM的操作,没定义的话,默认就是在FLASH里执行的。
以下是一个例子,其他论坛找来的,可以参考一下
1cmd定义:
ramfuncs : LOAD = FLASHJ,PAGE = 0
RUN = RAMH0,PAGE = 0
LOAD_START(_RamfuncsLoadStart),
LOAD_END(_RamfuncsLoadEnd),
RUN_START(_RamfuncsRunStart)
secureRamFuncs : LOAD = FLASHP, PAGE = 0 /* Used by InitFlash() in SysCtrl.c */
RUN =RAMH0 , PAGE = 0
LOAD_START(_secureRamFuncs_loadstart),
LOAD_END(_secureRamFuncs_loadend),
RUN_START(_secureRamFuncs_runstart)
2定义变量(装载或运行的起始地址)
extern Uint16 RamfuncsLoadStart;
extern Uint16 RamfuncsLoadEnd;
extern Uint16 RamfuncsRunStart;
extern Uint16 secureRamFuncs_runstart;
extern Uint16 secureRamFuncs_loadstart;
extern Uint16 secureRamFuncs_loadend;
3把要拷贝到RAM里的函数(eva_timer1_isr,eva_timer2_isr...)定义到段ramfuncs
#pragma CODE_SECTION(eva_timer1_isr, "ramfuncs");
#pragma CODE_SECTION(eva_timer2_isr, "ramfuncs");
#pragma CODE_SECTION(evb_timer3_isr, "ramfuncs");
4把要初始化的flash控制寄存器函数定义到段secureRamFuncs
#pragma CODE_SECTION(InitFlash, "secureRamFuncs")
void InitFlash(void);
// 声明中断函数
interrupt void eva_timer1_isr(void);
interrupt void eva_timer2_isr(void);
interrupt void evb_timer3_isr(void);
interrupt void evb_timer4_isr(void);
//初始化flash 控制寄存器函数为
void InitFlash(void)
{
asm(" EALLOW"); // Enable EALLOW protected register access
FlashRegs.FPWR.bit.PWR = 3; // Pump and bank set to active mode
FlashRegs.FSTATUS.bit.V3STAT = 1; // Clear the 3VSTAT bit
FlashRegs.FSTDBYWAIT.bit.STDBYWAIT = 0x01FF; // Sleep to standby transition cycles
FlashRegs.FACTIVEWAIT.bit.ACTIVEWAIT = 0x01FF; // Standby to active transition cycles
FlashRegs.FBANKWAIT.bit.RANDWAIT = 5; // Random access waitstates
FlashRegs.FBANKWAIT.bit.PAGEWAIT = 5; // Paged access waitstates
FlashRegs.FOTPWAIT.bit.OPTWAIT = 5; // Random access waitstates
FlashRegs.FOPT.bit.ENPIPE = 1; // Enable the flash pipeline
asm(" EDIS"); // Disable EALLOW protected register access
/*** Force a complete pipeline flush to ensure that the write to the last register
configured occurs before returning.Safest thing is to wait 8 full cycles. ***/
asm(" RPT #7 || NOP");
}
//复制中断向量到ram的函数为
void InitPieVectTable(void)
{
int16 i;
Uint32 *Source = (void *) &ieVectTableInit;
Uint32 *Dest = (void *) &ieVectTable;
EALLOW;
for(i=0; i < 128; i++)
*Dest++ = *Source++;
EDIS;
// Enable the PIE Vector Table
PieCtrl.PIECRTL.bit.ENPIE = 1;
}
4.在主函数中执行调用以下函数
/*初始化PIE矢量表*/
InitPieVectTable();
memcpy(&secureRamFuncs_runstart,
&secureRamFuncs_loadstart,
&secureRamFuncs_loadend - &secureRamFuncs_loadstart);
InitFlash();
memcpy(&RamfuncsRunStart,
&RamfuncsLoadStart,
&RamfuncsLoadEnd - &RamfuncsLoadStart); 35楼的问题
MODBUS中地址表是你自己定义的,只要每个地址可以对应一个数据就可以了 谢谢楼主了哈~ 郁闷死了,老板让我编写Modbus通讯程序,编译通过,就是调试不通,程序是从网上下的;然后改了一些地址映射;麻烦大侠指点一下
/********Modbus.h ********/
#ifndef MODBUS_H
#define MODBUS_H
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned char boolean; /* Boolean value type. */
typedef unsigned long int uint32; /* Unsigned 32 bit value */
typedef unsigned short uint16; /* Unsigned 16 bit value */
typedef unsigned char uint8; /* Unsigned 8 bit value */
//typedef signed long int int32; /* Signed 32 bit value */
//typedef signed short int16; /* Signed 16 bit value */
typedef signed char int8; /* Signed 8 bit value */
//------------MODBUS CMD-----------------------
//#define READ_N_COIL 01
//#define READ_N_DI 02
#define READ_HLD_REG 03
//#define READ_AI 04
//#define SET_1_COIL 05
//#define SET_1_HLD_REG 06
//#define SET_N_COIL 15
#define SET_N_HLD_REG 16
//------------UART_MODULE.Status---------------
#define IDLE_WAIT 0x00 // 空闲态,等待起始位
#define RECE_START 0x01 // 收到起始位,等待结束位
#define RECE_END 0x02 // 收到结束位,等待发送
#define SEND_START 0x03 // 发送起始位
#define SEND_END 0x04 // 发送完毕
//------------MODBUS REGS-----------------------
/*ModBus 寄存器缓冲区起始绝对地址,位于L1SARAM
ModBus 寄存器缓冲区0x009F00~0x009FFF,总长度256个字长度,512个字节 */
#define MBRRegAdd 0x009F00
/*只读寄存器
起始地址:0x009F00;
长度 :0x20
*/
#define MBDriveVerB6 *(int *)(MBRRegAdd)/* 传动型号寄存器组 */
#define MBSoftVerBt6 *(int *)(MBRRegAdd+0x03)/* 软件版本寄存器组 */
#define MBSoftVerBt8 *(int *)(MBRRegAdd+0x06)/* 出厂编号寄存器组 */
#define MBStatusReg1_2 *(int *)(MBRRegAdd+0x0A)/* 状态寄存器1 */
#define MBStatusReg2_2 *(int *)(MBRRegAdd+0x0B)/* 状态寄存器2 */
#define MBStatusReg3_2 *(int *)(MBRRegAdd+0x0C)/* 状态寄存器3 */
#define MBStatusReg4_2 *(int *)(MBRRegAdd+0x0D)/* 状态寄存器4 */
#define MBStatusReg5_2 *(int *)(MBRRegAdd+0x0E)/* 状态寄存器5 */
#define MBStatusReg6_2 *(int *)(MBRRegAdd+0x0F)/* 状态寄存器6 */
#define MBFreqOut_4 *(int *)(MBRRegAdd+0x10)/* 实际频率输出寄存器 */
/*可读写寄存器*/
#defineMBRWRegAdd 0x009F20
/*读写寄存器
起始地址:0x009F20;
长度 :0x10;
*/
/*EEPROM寄存器*/
/*可读写
起始地址:0x009F30;
长度 :0xCF;
*/
#defineMBEEPROMRegAdd 0x009F30
// ------------功能指令----------------------------
#define WORD_LO(xxx) ((char)((int)(xxx) & 255))/* 得到一个字的低位*/
#define WORD_HI(xxx) ((char)((int)(xxx) >> 8)) /* 得到一个字的高位*/
//#define B_PTR(var) ((char *)(void *) &(var))/*得到一个变量的地址(word宽度)*/
#define W_PTR(var) ((int *)(void *) &(var)) /*得到一个变量的地址(word宽度)*/
//#define MEM_B(x) (*( (char *)(x))) /*得到指定地址上的一个字节*/
#define MEM_W(x) (*( (int *)(x))) /*得到指定地址上的一个字*/
// 定义MODBUS数据结构
struct MODBUSDATA
{
unsigned int ID;
unsigned int FunCode;
unsigned int RegAdd;
unsigned int RegNum;
unsigned int Buf;
unsigned int Status;
unsigned int TxLen;
unsigned int RxLen;
unsigned int Point;
unsigned int TimeoutReg;
unsigned int TimeoutCounter;
};
//--------------------供外部调用函数-------------------------------
extern struct MODBUSDATA ModbusModule;
extern void ConfigureModbus(Uint16 brat,Uint16 SwitchRate);
extern void ModbusRTUSlaveRun(void);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif// end of DSP280x_SCI_H definition
//===========================================================================
// End of file.
//===========================================================================
// SC File $Revision:
// Checkin $Date:
//###########################################################################
//
// FILE:Modbus.c
//
// TITLE:
//
//###########################################################################
// $TI Release:
// $Release Date:
#include "DSP280x_Device.h" // DSP280x Headerfile Include File
#include "DSP280x_Examples.h" // DSP280x Examples Include File
#include "Modbus.h"
const unsigned charauchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
/* CRC低位字节值表*/
const unsigned charauchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;
struct MODBUSDATA ModbusModule;
// -------Modbus初始化----------0
void ConfigureModbus (void)
{
Uint16 i;
Uint16*dest_p;
dest_p=((Uint16*)MBRRegAdd);
for(i=0;i<256;i++)
{
*(dest_p+i)=0x0000;
}
ModbusModule.TxLen= 0;
ModbusModule.RxLen= 0;
ModbusModule.Point= 0;
//ModbusModule.ReTryTime =0;
ModbusModule.ID= 2;
ModbusModule.Status = SEND_END;
}//
/*
interrupt void ScibTxInt (void) // SCI-B
{
PieCtrlRegs.PIEACK.bit.ACK9 = 1;
if( ModbusModule.TxLen > 0 ){
ScibRegs.SCITXBUF= ModbusModule.Buf;
ModbusModule.TxLen--;
// ModbusModule.Point++;
// ModbusModule.Point %= 128; //
}else{//发送完毕
ModbusModule.Status = SEND_END; //状态切换
ModbusModule.Point=0;
ModbusModule.TimeoutReg=0;
}
}
*/
/*
//---------------------------------------------
// ScibRxInt MODBUS RTU
// 以两字符时间停顿为3.5个字符时间
// 程序用5ms时间判断 对应9600--5个字符时间
// 程序帧结束数据在主程序里面处理
//3.5字符数计数器公式:
//设波特率为 int BtRate(4800;9600;19200;)
//设开关频率volatile int SwitchRate(1K~20K,单位为KHZ)
//设3.5字符时间为delay3.5 =(int)(3.5*10*1000/BtRate);
//计数器Timeout3.5=delay3.5*SwitchRate;
//---------------------------------------------
interrupt void ScibRxInt (void) // SCI-B
{
Uint16temp;
PieCtrlRegs.PIEACK.bit.ACK9 = 1; //ACK复位
temp=ScibRegs.SCIRXBUF.all;
switch( ModbusModule.Status ){
case SEND_END: //4
ModbusModule.Status = RECE_START;
ModbusModule.Point=0;
case RECE_START: //1
ModbusModule.Buf = temp;
ModbusModule.Point++;
ModbusModule.RxLen = ModbusModule.Point;
break;
}
ModbusModule.TimeoutReg=0;
}
*/
//---------------------------------------------
//程序第二部分:MODBUS 协议解析与构造
// CRC16
// 协议帧构造
// 协议帧解析
//---------------------------------------------
//---------------------------------------------
// CRC16 calculate
// <-Modbus Protocol English pdf
// ptr calculate start point
// len calculate data length
//---------------------------------------------
Uint16 GetCRC16 (Uint16 volatile * puchMsg,Uint16 usDataLen)
{
unsigned char uchCRCHi = 0xFF ; /* 高CRC字节初始化 */
unsigned char uchCRCLo = 0xFF ; /* 低CRC 字节初始化 */
Uint32 uIndex ; /* CRC循环中的索引 */
while (usDataLen--) /* 传输消息缓冲区 */
{
uIndex = uchCRCHi ^ *puchMsg++ ; /* 计算CRC */
uchCRCHi = uchCRCLo ^ auchCRCHi ;
uchCRCLo = auchCRCLo ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}//uint16 crc16(uint8 *puchMsg, uint16 usDataLen)
//---------------------------------------------
// RTU Set N Hold Register
// CMD=16 SET_N_HLD_REG
// Constructe Answer Frame
//---------------------------------------------
voidModbusSlaveSetNHldRegAnswer ( Uint16 board_adr,Uint16 start_address,Uint16 lenth)
{
Uint16 i=0,j=0;
ModbusModule.Buf = board_adr;
ModbusModule.Buf = SET_N_HLD_REG;
ModbusModule.Buf = WORD_HI(start_address);
ModbusModule.Buf = WORD_LO(start_address);
ModbusModule.Buf = WORD_HI(lenth);
ModbusModule.Buf = WORD_LO(lenth);
j=GetCRC16(ModbusModule.Buf,i);
ModbusModule.Buf = WORD_LO(j);
ModbusModule.Buf = WORD_HI(j);
ModbusModule.TxLen = i;
ModbusModule.Point = 0;
}
//---------------------------------------------
// RTU Read Hold Register
// CMD=03 READ_HLD_REG
// Constructe Answer Frame
//---------------------------------------------
voidModbusSlaveReadHldRegAnswer ( Uint16 board_adr,Uint16 *com_buf,Uint16 lenth)
{
Uint16 i=0,j=0;
ModbusModule.Buf = board_adr;
ModbusModule.Buf = READ_HLD_REG;
ModbusModule.Buf = lenth<<1;
for(j=0;j<lenth;j++){
ModbusModule.Buf = WORD_HI( * (com_buf+j) );
ModbusModule.Buf = WORD_LO( * (com_buf+j) );
}
j=GetCRC16(ModbusModule.Buf,i);
ModbusModule.Buf = WORD_LO(j);
ModbusModule.Buf = WORD_HI(j);
ModbusModule.TxLen = i;
ModbusModule.Point = 0;
}
//---------------------------------------------
// RTU从站接收分析
// 3 READ_HLD_REG
// 16 SET_N_HLD_REG
// 返回值: 0OK
// 1 CRC校验错误
// 2 站号不匹配
// 3 读地址无效
// 4 16写地址不匹配
// 5 16写数据字数不匹配
//---------------------------------------------
Uint16 RTUSlaveFrameAnalyse (void)
{
Uint16 i;
Uint16*dest_p;
Uint16 crc_result, crc_tmp;
Uint16 RegNum;
int16RegAddr;
crc_tmp= ModbusModule.Buf<<8;
crc_tmp += ModbusModule.Buf;
crc_result=GetCRC16(ModbusModule.Buf,ModbusModule.RxLen-2);
if ( crc_tmp != crc_result ) // CRC 校验正确
{
return 1;
}
if ( ModbusModule.ID != ModbusModule.Buf )
{
return 2;
}
ModbusModule.FunCode=ModbusModule.Buf;
RegAddr= (ModbusModule.Buf<<8) + ModbusModule.Buf-0x4000;
RegNum = (ModbusModule.Buf<<8) + ModbusModule.Buf;
switch (ModbusModule.FunCode)
{
case READ_HLD_REG: //3
if(RegAddr>0xFF||RegAddr<0) return 3;
if((RegAddr+RegNum-1)>0xff) return 3;
dest_p=((Uint16*)(MBRRegAdd+RegAddr+RegNum-1));
ModbusSlaveReadHldRegAnswer(ModbusModule.ID,dest_p,RegNum);
break;
//case SET_1_HLD_REG: //6
case SET_N_HLD_REG: //16
if(RegAddr>0x2F||RegAddr<0x20) return 4;
if((RegAddr+RegNum-1)>0x2f) return 4;
if((RegNum<<1) != ModbusModule.Buf)return 4;
dest_p=((Uint16*)(MBRRegAdd+RegAddr+RegNum-1));
for (i=0; i<ModbusModule.Buf; i+=2)
{
*(dest_p + i/2) = ( ModbusModule.Buf<<8 ) + ModbusModule.Buf;
}
ModbusSlaveSetNHldRegAnswer(ModbusModule.ID,RegAddr,RegNum);
break;
}//end switch
return 0;
}
//---------------------------------------------
// ModbusRTUSlaveRun
// 通讯由主站发起,从站初始化为接收,并相应的做出回应。
// 站号在初始化中有设置,以后不再更改。
//---------------------------------------------
void ModbusRTUSlaveRun (void)
{
switch (ModbusModule.Status){
case IDLE_WAIT ://0
ScibRegs.SCITXBUF = ModbusModule.Buf;
ModbusModule.TxLen--;
ModbusModule.Status = SEND_START;
break;
case SEND_START ://3
asm("nop");
break;
case SEND_END ://4
if (ModbusModule.TimeoutReg>=10)
{//超时10ms
//ModbusModule.ReTryTime++;
ModbusModule.TimeoutReg=0;
//InitSci_B(); //***********
}
break;
case RECE_START ://1
if (ModbusModule.TimeoutReg>=5)
{//接收帧结束
ModbusModule.Status = RECE_END;
}
break;
case RECE_END ://2
if(RTUSlaveFrameAnalyse()==0 )
{//帧解析正确
ModbusModule.Status =IDLE_WAIT;
}
else
{ //帧解析不正确
ModbusModule.Status =SEND_END;
}
break;
}
} void ModbusRTUSlaveRun (void) ;函数我放在一个定时器中断里不断查询状态;ModbusModule.TimeoutReg计数器放在一个EPWM定时器中断里(优先级最高,保证计数准确性);使能串口接受中断,发送中断,调试时只在主循环循环,不进入串口中断,急啊 这么久了,才又有机会调试F2812的SCI模块。
虽然还是不能完全理解它的TX FIFO模块的工作原理,但是现在基本可以用了。
SCI-B的配置如下:
// Initialize SCI-B:
ScibRegs.SCICCR.all = 0x0007; // 1 stop bit,No loopback
// No parity,8 char bits,
// async mode, idle-line protocol
ScibRegs.SCICTL1.all = 0x0003; // enable TX, RX, internal SCICLK,
// Disable RX ERR, SLEEP, TXWAKE
ScibRegs.SCICTL2.bit.TXINTENA = 1;
ScibRegs.SCICTL2.bit.RXBKINTENA = 1;
ScibRegs.SCIHBAUD = SCIBBAUDH;
ScibRegs.SCILBAUD = SCIBBAUDL;//波特率是9600的,和电脑的串口调试助手联机调试方便
//ScibRegs.SCICCR.bit.LOOPBKENA = 1; // 不开自测试模式,因为是和电脑实际的联机调试的
ScibRegs.SCIFFTX.all = 0xC020;
ScibRegs.SCIFFRX.all = 0x0025;
ScibRegs.SCIFFCT.all = 0x00;
SciaRegs.SCIPRI.all = 0x10;
ScibRegs.SCICTL1.all = 0x0023; // Relinquish SCI from Reset
ScibRegs.SCIFFTX.bit.TXFIFOXRESET = 1;//打开这个,SCIB就会进入发送中断,貌似复位时就会产生一个TXRDY中断
ScibRegs.SCIFFRX.bit.RXFIFORESET = 1;
发送中断程序如下:
interrupt void SCITXINTB_ISR(void) // SCI-B
{
// Insert ISR Code here
PerformScibTx();
// ClearSCIB TxFiFo Interrupt flag
ScibRegs.SCIFFTX.bit.TXINTCLR=1;
// To receive more interrupts from this PIE group, acknowledge this interrupt
PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
// Next two lines for debug only to halt the processor here
// Remove after inserting ISR Code
//asm (" ESTOP0");
//for(;;);
}
发送数据函数如下:
定义了一个全局变量bool ScibTxFlag = true用来进行单次发送测试
void PerformScibTx(void)
{
Uint16 i;
if (ScibTxFlag == true)
{
for(i = 0; i < 8; ++i)
{
ScibRegs.SCITXBUF = i; // Send data
}
ScibTxFlag = false;
}
else ScibRegs.SCIFFTX.bit.TXFIFOXRESET = 0;
}
发送FIFO的级别为0,就是说发送FIFO为空时进入发送中断。
中断里面只写一次数据。
实际联机调试发现,程序运行后,会进入两次发送中断,第一次进入时,向TXFIFO写入了8个数据,程序完成第一次中断后,上位机收到7个数据,然后程序进入第二次发送中断,这次并不想TXFIFO中写入数据,程序完成第二次中断后,上位机收到了1个数据。两次发送中断,把自己想要发送的8位数据发送完成了。但是如果不TXFIFOXRESET = 0的话,程序会不停的进入发送中断,这个就无法理解了。
一句话,TI DSP的TXFIFO模块,用起来真是不同寻常,和别人的不一样。
谢谢楼主和各位兄弟的帮助啦。 关于MODBUS的问题,请另开一贴讨论,这个和CPU关系不大呢
建议到ARM或者AVR版块发贴,我虽然也做过,但实在没精力帮兄弟看程序了,见谅 楼主您好:
首先感谢您回复了这么多问题,看了十分有收获,现在我说下我的疑问 呵呵
我看书上说2812在启动时需要一个跳转向量跳转到_c_int00,这样才能跳转到c代码
我在烧写时验证了一下 确实是这样
但是当我load时我写的程序里根本没有跳转指令也能正常执行,也能正常进入main
这是怎么回事呢,是不是load和烧写时不一样呢?load时不需要跳转指令也会自动进入main函数吗? 非常有收获啊 看你的cmd里面,cint00在这里定义的 有关OSHT和CBC的疑问
请教一下2808的TZ模块中,有两个模式CBC和OSHT,但是对于他们的区别,TI的datasheet上并没有介绍得很清楚。因此有些不明吧。
第一CBC我知道好像是每个PWM周期都会检测一下引脚相关输入引脚的状态,如果状态为高电平,就恢复相应输入引脚的功能,但是这是相应的标志位:CBC和INT不会被清除,必须要手工清除,那么是不是着来年改革标志位不会再次出发中断了呢?
第二对于OSHT我不太明白是不是他一旦检测到输入引脚为地电平,就不会在周期性的检测相应输入引脚的状态了呢?
第三,CBC状态时不管我什么时候清除标志位,他都会只在CTR=0的时刻回复相应输出的功能,OSHT状态,什么时候能够解除呢?是不是只要我将相应的OST和INT标志位清零,他就会解除?
以上是我的是那个疑问,希望工程师能帮助解释就。 楼上的问题,十分抱歉,最近比较忙,没时间帮你查找资料了,自己先想想办法吧
5.1后我再来看这个问题。 已经解决了,虽然提问了,但是自己也在努力研究尝试,已经解决了。但还是感觉楼主。 楼上将你解决问题的方法发上来呀,大家共同进步,互相帮助 楼主帮我解决下我的问题阿,都把我跳过了..... 在发一下问题吧
楼主您好:
首先感谢您回复了这么多问题,看了十分有收获,现在我说下我的疑问 呵呵
我看书上说2812在启动时需要一个跳转向量跳转到_c_int00,这样才能跳转到c代码
我在烧写时验证了一下 确实是这样
但是当我load时我写的程序里根本没有跳转指令也能正常执行,也能正常进入main
这是怎么回事呢,是不是load和烧写时不一样呢?load时不需要跳转指令也会自动进入main函数吗? 呵呵,楼上不好意思啊
load和烧写时不一样
***********************************************************************
* Function: codestart section
*
* Description: Branch to code starting point
***********************************************************************
.sect "codestart"
code_start:
.if WD_DISABLE == 1
LB wd_disable ;Branch to watchdog disable code//load时执行这里
.else
LB _c_int00 ;Branch to start of boot.asm in RTS library//FLASH中执行这里
.endif 请教楼主:
我做毕业设计,就用到F2812的SCI和打印机相连,能用DSP控制打印机。大概就是打印出银行的排队小票。可以说说思路,现在还是不太理解从哪改起。我有PC机与SCI通信的实验例子,就是PC机向2812传一个字符。 54楼
1、你需要了解打印机的控制协议,发送什么数据给它,会打印一个字符?发什么数据会换行?等等都要搞清楚
2、实现2812的SCI发送,这个TI有例子程序,楼上也有相关讨论的贴子可以参考
3、用2812实现协议,控制打印机
这个毕业设计难度并不大,只是用到了SCI而已 楼主:
我是54楼的,还是想再问一下,我现在不太清楚怎么将打印机的控制命令字通过SCI发给打印机,是用汇编和C语言混编的形式,用asm()的那个吗,问题有点弱,您说仔细一些,我之前没接触过这些,谢谢了。 楼上,你要先学会用SCI发送数据,就象你要和人交流,必须先学会说话一样。
至于怎么用SCI发送数据,TI有例程的哦,自己看一下,然后实际运行一下会有比较直观的了解 做板凳听听课!呵呵 CBC就是周期性的检测相应引脚的状态,每个周期结束的时候,如果相应的输入引脚为高电平,就会自动退出tz状态,相应的输出引脚回复pwm功能。这个我感觉很适合做限流。而OSHT就是一次触发模式,他是只要进入tz模式,除非手动清除标志位,否则不会退出tz模式。因此需要手动结束tz模式。以上是我试验以及和其他人讨论的结论,不知道对不对,发上来和大家一起分享。
另外之前我提过的SCI的fifo模式,也做了个实验,fifo如果设定成16个字节的话,每次发送的时候,可以使用for循环一次向TXBUF中写入16个数据。直到全部发送完成才会产生TX中断。同样接收的时候,只有到达了你设定的数量,才会产生中断,这是你可以通过for循环一次性的将全部数据读出。
但是有一点不太清楚,如果初始化的时候设定了fifo的发送中断时当发送缓冲器中的数据小于2(或者直接就是默认值0)就会产生中断,那在初始化完成后,实际上发送缓冲器中并没有数据,但是却没有出发中断,知道我第一次向其中写入数据才会出发中断,看到有一些例程里面可以通过清楚发送中断标志位来使能发送,而他仅仅在发送中断中才会将数据传输到发送缓冲器中。因此不太明白是不是在初始化完成后,通过清楚发送中断的标志位和将fifo功能使能位置一,就可以出发发送中断,然后直接通过中断将数据发送出去?
而在中断外部不需要先向发送缓冲器中写入一次数据?
以上就是我这几天的实验所得,希望大家能够一起讨论。 大家继续讨论,盖高楼 非常感谢楼主耐心指导,我也是在做SCI通信程序,碰到点问题,请楼主指导:
我看过很多例程,现在想编一个利用中断方式接收道不同指令后,由DSP回复相应内容的程序.于是我先制定了协议.我发现如果用FIFO发送接收的话,因为接收情况太多,所以我在接收中断里采用选择结构.但是发送的内容也不一样,在发送中断里也要相应的发出相对应的内容,这样一来,我有点束手无策了,请文楼主又没什么好方法呢?还有,就是FIFO只能传16个字节,而我要发20多个字节,我试了,如果就平常那样发的话,中间的数据会丢失,这也不好解决了...请楼主帮下,谢谢. 那你必须将这些命令变成16个字节,当然你可以使用一个变量来统计发送的个数,这样就可以接着上次的发送。 61楼,你将接收/发送数据都发到缓冲区,缓冲区可以开大一些,比如512字节。然后中断里只是把缓冲区数据发送出去,将接收数据放到接收缓冲区,这样中断里就比较简单了。
然后可以在其他地方判断缓冲区里的数据;一般是贞结束后再处理接受缓冲区里的数据 62楼,我这些要发的数据已经定好了,而且发的内容不会一样,长度定了,不能改了。。。
63楼,如果采纳楼主的意见,那意味着我不能用FIFO了吧,就只能用普通的中断吗? 一样可以用FIFO,并不冲突
比如你要运送货物到一个地方,如果把缓冲区比做火车(容量大),FIFO比做卡车
你可以直接用卡车送。
现在有火车了,你可以将所有东西先装到火车上,到达目的火车站后,再由卡车分别送到最终客户手里
这样对发送来说,就只要将货物送到火车站了,接收时只要从火车站取货然后使用
对于是否用FIFO,就是使用卡车还是人扛运送火车站的货物的问题,随便你了 楼上的意思还是分别发送(需要多个中断),但是你要判断如果接到了指定数量的指令,在一起冲数组或者缓冲区里读取。 哦~我现在已经实现接收到某一命令就发送相应数据的功能了。我的做法是在发送中断内加入选择结构,将发送与接收的内容对应。
其实我把要发送的数据都放在对应的数组里了,每次收到不同命令时就发送对应数组的内容,这是不是跟楼主说的分配一个缓冲区给数据一样,而接受的数据我也放在数组里了。
而且,据我的理解,用FIFO的话,拿发送来说,数据是先发到FIFO里,再到scitxbuf,这样一来,字节还是限制为16字节,一旦超过了时,我用串口调试时就发生中间部分缺失问题,不知道我的理解是不是正确,望大家指正和指导,谢谢。 每次最多发送16字节,如果超过这个大小就要分多次发送,要预先按照16字节规划一下。分多个发送中断发送。接受一样,可以使用结束标志,当接到结束标志的时候就意味着全部接受完成,然后就可以处理了 您好,我有2个问题:
1) F2812 里声明一个数组,有大小限制吗?
例如: A 可以编译通过
A 编译出错
提示: error: the size of an array must be greater than zero
------------------------------------------------------------
2)如果需要大数组的话,该什么处理呢?
------------------------------------------------------------
谢谢!~~ 68楼:分多次发的话,是要将内容要分放在几个数组中吗,还是都放在一个数组里,发送先发16字节,发送完时未检测到结束标志再继续发。。这样又牵扯到另一个问题,每个数组都要有个结束标志了。请问结束标志可以定为那些字符?还有,我想在发送数据时在数据前加一位命令字,一位数据长度的话,直接加在数据所在的数组里的话,由于命令字和长度都是16进制的数字,而数据是字母的话,在定义这个数组时怎么定义,这是C的问题了,我试了几种方法都出现错误了,特请求教。 我的意思是,比如你有20个字节需要发送,那么你就在这20个字节后面加一个停止标志字节(自己设定的)。然后使用一个变量来技术,只要没有接到这个停止标志字节,就认为发送的是同一条指令,然后放在同一个数组里面,这样不需要管经过几次中断,最终都可以得到完整的命令组。但是你在发送的时候最多一次只能发送16个字节,因此需要在发送的时候人为地将这20个字节+一个结束字节分成两组发送。 我今天试了下~我设定数据末尾都有个换行符,在发送中断中先发送前十六个字节给SCITXBUF,然后判断第16个字节是否为换行符(在这我想问下,怎么选中SCITXBUF中的数据啊,或许是到FIFO中选?我当时是直接检测我放数据的数组中第16个字节)。如果不是的话,我通过循环赋值语句把数组接下来未发的数据再发给SCITXBUF。这样的话,我发现还是会少数据。
于是,我在判断语句中加了检测发送缓冲是否为空和FIFO中是否为空两条语句跟前面的判断语句相与,以此来作为判断是否发未发完的数据。但是,问题是在中断里面加这条语句,我在串口里只看到前16格字节,后面部分丢失了。。。
我的结论是可能中断未结束,那两个作为判断的标志位不符合条件,就没继续发送了后面数据了。
看到你的建议中,变量计数的作用是什么?还有“没接到标识符,认为发送的是同一条指令”这个我试了,出现了上面我说的数据重叠现象。“放在一个数组里”这个不太明白,我的数据都是分数组放的,发送时是把数组里的数据给SCITXBUF,发完了还要放在同一个数组里吗?
对了,请问你能加我QQ吗?那样联系方便些。我做这个不久,需要阁下指点。谢谢。
我的QQ782853407.验证写DSP就好了。 我不能理解2812的通用定时器周期寄存器为什么存在?不是已经有了个通用定时器比较寄存器么?郁闷 问题已经明白了。。。 72楼,当有FIFO空中断时,你写16个字节到FIFO就可以了。这样是不会丢数据的哦
还是我65的火车方式来说,假设火车有16节车厢,你每次放满16节车厢后,火车就开走了咯。等火车再回来(FIFO为空)你就可以再放16节车厢的货物。这样是不会丢东西的
如果丢了,要检查是否在FIFO不空的情况下又写了16个字节进去,覆盖了未发送完毕的数据。 恩,我就是不知道火车是什么时候回来的。。所以不知道该在什么时候继续发剩下的数据。。 火车回来的时候会有中断,因此发送工作应该在中断中进行,而且当你初始化中使能了fifo的匹配中断后,SCI会立刻进入一次中断,在中断中奖要发送的数据按照最多16个字节的格式发送就可以了。这样就好像你只能在月台上像火车里面送东西,而月台在火车没有到之前是不开放的,因此不会出现覆盖的问题。 但是要在中断中发送两次,这个不会覆盖么?。。
我用接收中断触发发送中断,在发送中断里发送对应数据,当发送完16字节时检测结尾不是结束符,就又触发发送中断吗?这样在发送中断里触发发送中断可以吗?好像不行吧。就是这我卡住了。
如果不触发发送中断,直接检测后又把剩余数据给SCITXBUF,就会丢失中间部分了。。。 请教下我的PWM设置为递增递减模式,
一个是0占空比为高电平,100%占空比为低电平
一个是100%占空比为高电平,0占空比为低电平
我在调试的时候,从0占空比升到20%,1毫秒后 在降低为0%
结果出现一个错误的信号~如图圆圈处~
请教DX怎么回事?
http://cache.amobbs.com/bbs_upload782111/files_15/ourdev_446087.jpg
(原文件名:1111.jpg) 楼上的没有明白我的意思,出发中断只要你设定的匹配条件满足就会发生,你可以将匹配之设置成0,这样发送完前16个字节,优惠自动触发发送中断,在发送后面的字节。 还有,楼上的没有看到你的程序怎么可能知道问题出在哪里? PWM的设置:都是一样的
pwminit(void){
EPwm1Regs.TBPRD = 1500;
EPwm1Regs.TBPHS.half.TBPHS=0;
EPwm1Regs.TBCTR=0;
EPwm1Regs.TBCTL.bit.CTRMODE = 2;
EPwm1Regs.TBCTL.bit.PHSEN = 0;
EPwm1Regs.TBCTL.bit.PRDLD = 0;
EPwm1Regs.TBCTL.bit.SYNCOSEL = 0;
EPwm1Regs.TBCTL.bit.HSPCLKDIV =0;
EPwm1Regs.TBCTL.bit.CLKDIV = 0;
EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0;
EPwm1Regs.CMPCTL.bit.SHDWBMODE = 0;
EPwm1Regs.CMPCTL.bit.LOADAMODE = 0;
EPwm1Regs.CMPCTL.bit.LOADBMODE = 0;
EPwm1Regs.AQCTLA.bit.CAU = 1;
EPwm1Regs.AQCTLA.bit.CAD = 2;
EPwm1Regs.AQCTLB.bit.CBU = 2;
EPwm1Regs.AQCTLB.bit.CBD = 1;
}
main(){
EPwm1Regs.CMPA.half.CMPA=100; //A的输出占空比
EPwm1Regs.CMPB=100;
delay(1);
EPwm1Regs.CMPA.half.CMPA=0; //A的输出占空比
EPwm1Regs.CMPB=0;
delay(1);
}
就是这样的哈~ 这个波形看上去很正常呀?你在后面CMPA和CMPB都变成了0,也就是说对于A来说,一开始就会变成低电平,然后知道周期完成,才会变成高电平你个,而B正好相反。 哦,原来这样哈,谢谢LS了~ 楼主,MCBSP配置成SPI,一台为主,一台为从进行通信,先设置主机循环发送数据,再配置从机接收数据,但配置完从机后,主机MOSI脚上的电平低了一半,不知是何原因 请大家帮忙,F2812本身能提供当前时间的功能嘛?我想用打印机打出日期和时间来,有什么好办法吗?
急需解答,希望知道的能帮一下。 85楼,应该是从机的MISO为低导致的
86楼,F2812本身没有时间功能,最好扩展时钟芯片。另外用定时器自己做个时钟也是可以的,不过会有误差,掉电保持也是个问题 楼主,我说的是MOSI,主机的MOSI连接从机的MOSI,跟MISO是分开的 void InitMcbspaGpio(void)
{
EALLOW;
/* Configure McBSP-A pins using GPIO regs*/
// This specifies which of the possible GPIO pins will be McBSP functional pins.
// Comment out other unwanted lines.
GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 2; // GPIO20 is MDXA pin
GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 2; // GPIO21 is MDRA pin
GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 2; // GPIO22 is MCLKXA pin
//GpioCtrlRegs.GPAMUX1.bit.GPIO7 = 2; // GPIO7 is MCLKRA pin (Comment as needed)
GpioCtrlRegs.GPBMUX2.bit.GPIO58 = 1; // GPIO58 is MCLKRA pin (Comment as needed)
GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 2; // GPIO23 is MFSXA pin
//GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 2; // GPIO5 is MFSRA pin (Comment as needed)
GpioCtrlRegs.GPBMUX2.bit.GPIO59 = 1; // GPIO59 is MFSRA pin (Comment as needed)
/* Enable internal pull-up for the selected pins */
// Pull-ups can be enabled or disabled by the user.
// This will enable the pullups for the specified pins.
// Comment out other unwanted lines.
GpioCtrlRegs.GPAPUD.bit.GPIO20 = 0; // Enable pull-up on GPIO20 (MDXA)
GpioCtrlRegs.GPAPUD.bit.GPIO21 = 0; // Enable pull-up on GPIO21 (MDRA)
GpioCtrlRegs.GPAPUD.bit.GPIO22 = 0; // Enable pull-up on GPIO22 (MCLKXA)
//GpioCtrlRegs.GPAPUD.bit.GPIO7 = 0; // Enable pull-up on GPIO7 (MCLKRA) (Comment as needed)
GpioCtrlRegs.GPBPUD.bit.GPIO58 = 0; // Enable pull-up on GPIO58 (MCLKRA) (Comment as needed)
GpioCtrlRegs.GPAPUD.bit.GPIO23 = 0; // Enable pull-up on GPIO23 (MFSXA)
//GpioCtrlRegs.GPAPUD.bit.GPIO5 = 0; // Enable pull-up on GPIO5 (MFSRA) (Comment as needed)
GpioCtrlRegs.GPBPUD.bit.GPIO59 = 0; // Enable pull-up on GPIO59 (MFSRA) (Comment as needed)
/* Set qualification for selected pins to asynch only */
// This will select asynch (no qualification) for the selected pins.
// Comment out other unwanted lines.
GpioCtrlRegs.GPAQSEL2.bit.GPIO20 = 3; // Asynch input GPIO20 (MDXA)
GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 3; // Asynch input GPIO21 (MDRA)
GpioCtrlRegs.GPAQSEL2.bit.GPIO22 = 3; // Asynch input GPIO22 (MCLKXA)
//GpioCtrlRegs.GPAQSEL1.bit.GPIO7 = 3; // Asynch input GPIO7 (MCLKRA) (Comment as needed)
GpioCtrlRegs.GPBQSEL2.bit.GPIO58 = 3; // Asynch input GPIO58(MCLKRA) (Comment as needed)
GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 3; // Asynch input GPIO23 (MFSXA)
//GpioCtrlRegs.GPAQSEL1.bit.GPIO5 = 3; // Asynch input GPIO5 (MFSRA) (Comment as needed)
GpioCtrlRegs.GPBQSEL2.bit.GPIO59 = 3; // Asynch input GPIO59 (MFSRA) (Comment as needed)
EDIS;
}
void init_mcbsp_spi()
{
// McBSP-A register settings
McbspaRegs.SPCR2.all=0x0000; // Reset FS generator, sample rate generator & transmitter
McbspaRegs.SPCR1.all=0x0000; // Reset Receiver, Right justify word, Digital loopback dis.
McbspaRegs.PCR.all=0x0f08; //(CLKXM=CLKRM=FSXM=FSRM= 1, FSXP = 1) clkxm = 1 ,so it is spi master
McbspaRegs.PCR.bit.CLKXM = 1;
McbspaRegs.SPCR1.bit.DLB = 0;//disable loopback spi
McbspaRegs.SPCR1.bit.CLKSTP = 2; // Together with CLKXP/CLKRP determines clocking scheme
McbspaRegs.PCR.bit.CLKXP = 0; // CPOL = 0, CPHA = 0 rising edge no delay
McbspaRegs.PCR.bit.CLKRP = 0;
McbspaRegs.RCR2.bit.RDATDLY=01; // FSX setup time 1 in master mode. 0 for slave mode (Receive)
McbspaRegs.XCR2.bit.XDATDLY=01; // FSX setup time 1 in master mode. 0 for slave mode (Transmit)
McbspaRegs.RCR1.bit.RWDLEN1=2; // 16-bit word
McbspaRegs.XCR1.bit.XWDLEN1=2; // 16-bit word
McbspaRegs.SRGR2.all=0x2000; // CLKSM=1, FPER = 1 CLKG periods
McbspaRegs.SRGR1.all= 0x000F; // Frame Width = 1 CLKG period, CLKGDV=16
//clkGDV = 0xf; spi clk = 100M/4/(0xf+1)
//SRG input is LSPCLK (SYSCLKOUT/4)
if(spi_slave == 1)//slave
{
McbspaRegs.PCR.bit.CLKXM = 0;//spi slave,clkx input
McbspaRegs.PCR.bit.FSXM = 0;// ss input
McbspaRegs.PCR.bit.FSXP =1;
McbspaRegs.RCR2.bit.RDATDLY = 0;
McbspaRegs.XCR2.bit.XDATDLY = 0;
McbspaRegs.SRGR2.bit.CLKSM = 1;//clk source lspclk
McbspaRegs.PCR.bit.SCLKME = 0;
McbspaRegs.SRGR1.bit.CLKGDV = 0;
}
McbspaRegs.SPCR2.bit.GRST=1; // Enable the sample rate generator
DELAY_US(10); // Wait at least 2 SRG clock cycles
McbspaRegs.SPCR2.bit.XRST=1; // Release TX from Reset
McbspaRegs.SPCR1.bit.RRST=1; // Release RX from Reset
McbspaRegs.SPCR2.bit.FRST=1; // Frame Sync Generator reset
} 以上是我的初始化程序,麻烦楼主帮忙看一下 感谢楼主,问题已经解决,就是管脚接错了 大家继续盖楼啊
500楼,我就发我的四层2808核心板PCB,经过工业现场考验的哦 标记! 楼主在不,我用28335,sizeof(int),sizeof(char),sizeof(short)结果都是1,而且拷贝内存的时候也发现,这些数据类型好象都是32位一样? 我用的是f2808
想移植一个Modbus通讯程序,我把所有寄存器变量连续放在初始地址在0x009F00
通过在头文件用宏定义
#define MBRRegAdd 0x009F00 ,
然后
#define MBDriveVerB6 *(int *)(MBRRegAdd)/* 传动型号寄存器组 */
#define MBSoftVerBt6 *(int *)(MBRRegAdd+0x03)/* 软件版本寄存器组 */
#define MBSoftVerBt8 *(int *)(MBRRegAdd+0x06)/* 出厂编号寄存器组 */
#define MBStatusReg1_2 *(int *)(MBRRegAdd+0x0A)/* 状态寄存器1 */
#define MBStatusReg2_2 *(int *)(MBRRegAdd+0x0B)/* 状态寄存器2 */
#define MBStatusReg3_2 *(int *)(MBRRegAdd+0x0C)/* 状态寄存器3 */
#define MBStatusReg4_2 *(int *)(MBRRegAdd+0x0D)/* 状态寄存器4 */
#define MBStatusReg5_2 *(int *)(MBRRegAdd+0x0E)/* 状态寄存器5 */
#define MBStatusReg6_2 *(int *)(MBRRegAdd+0x0F)/* 状态寄存器6 */
#define MBFreqOut_4 *(int *)(MBRRegAdd+0x10)/* 实际频率输出寄存器 */
哪位大侠指点一下
不知道这样可行不? 95楼,可行
但不方便,可以使用结构体来实现
94楼,请看CCS关于变量类型及位宽的帮助 楼主,你好!
请教两个问题,DSP F2808内部的FLASH可以划分一个区域或者块做为存储数据吗(即作为EEPROM用)?
还有就是在使用SPI模块时,CS那个管脚配置成普通IO口(程序里面手动拉低使能)时可以正常使用外设,
但配置成SPI模块专用的CS引脚时,却不能正常工作,这是为什么呢? 请教一下,epwm模块里面的AQ寄存器组里面有一个AQSFRC和AQCSFRC寄存器。其中的单次强制和连续强制有什么区别呢?是不是和TZ里面的OSHT和CBC是一样的呢?我在想是不是能利用这个选项来单独控制某一路epwm引脚产生或者不产生epwm信号,如果不行的话,使用什么方法可以实现呢(使用cmpa或者B来控制占空比除外,感觉那种比较麻烦)。 97楼,有条件就用外部存储器吧,也没几个钱,都用DSP了,咱别那么抠
SPI的CS自己控制和自动控制,我都用过,是没问题的哦,自动控制时,你用示波器看一下时序是否符合器件要求吧
98楼,你这个问题我暂时不清楚,有我空看一下手册