用modbus上位机程序给下位机发送指令可以不用modbus协议,直接给寄存器发送指令么

查看: 46399|回复: 313
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;
假如我想用TXFIFO的话,例如一次发16个字节,应该怎么配置SCIFFTXA寄存器呢?
用TXFIFO的话,可以不用一个字节一个字节等待发送完毕,一次性写入16个字节就可以啦,这样理解对吧?
期待楼主的解惑,先行谢过啦!
LZ辛苦了,无私的人,
我贴一个2808的TX FIFO例子你看一下,其实TI提供了很全的例子,所以你先看一下TI的代码,然后修改一下就OK
interrupt void sciaTxFifoIsr(void)
& & Uint16
& & 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
& & & & for(i=0;i&8;i++)
& & & && & rdataA=SciaRegs.SCIRXBUF.& & & &&&// 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外设例程 (原文件名: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中定义了一个位定义结构体
& &unsigned& &acc:1;
& &unsigned& &dec:1;
& &unsigned& &stopmod:2;
& &unsigned& &dirsel:1;
& &unsigned& &dirfor:1;
& &unsigned& &save:1;
想在2.C操作这个变量,就在2.C顶头 extern struct runcon4_
但是编译不通过;
&2.c&, line 226: error: identifier &runcon4_flag& is undefined
然后 我保留 extern struct runcon4_
删除在2.C引用runcon4_flag,再编译,就编译通过,不过警告“&Modbus.c&, line 23: warning: a storage class may not be specified here”,我双击它,就跳转到 “extern struct runcon4_”
请问大侠这是怎么回事啊,
26楼,这个你参考一下DSP28xx_Gpio.h中结构体的用法
25楼,请参考
TMS320x280x DSP
模数转换器(ADC)
SPRU716.pdf
请教楼主DX下
我用2808,但现在可以调试,运行OK
但我下载到FLASH中,就不运行了`
只是个普通的LED程序,我参考模板写的
要将程序在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给看一下~不胜感谢!
点击此处下载
(原文件名:BLDC.rar)
那你用光盘里综合实验的工程做模板,在其基础上添加自己的代码吧
谢谢楼主回答~
我知道问题出那了
我少加了个 DSP280x_CodeStartBranch.asm 文件,没有这个文件,编译也不回出错~
奇怪哈,不知道这文件是做什么的?
楼主的板子不错,程序写的满好的~我现在就用的楼主的模板程序~呵呵~DSP不简单哈~
感谢楼上的肯定
不过我个人认为,DSP并不难,难的是基于DSP的应用,不管是ARM、DSP、51或者其他CPU,从使用CPU的角度来说都差不多,道理也是相通的。就象从南京到上海,可以采用步行、自行车、汽车等等交通方式,但前提是你必须知道路线(对你的目标应用要熟悉),用何种交通方式,只是效率问题。
另,最近新增了12864图形LCD的程序,需要可以best2002@索取,效果如下,控制器为SED1565兼容
(原文件名: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 RamfuncsLoadS
extern Uint16 RamfuncsLoadE
extern Uint16 RamfuncsRunS
extern Uint16 secureRamFuncs_
extern Uint16 secureRamFuncs_
extern Uint16 secureRamFuncs_
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 *) &ieVectTableI
& && &&&Uint32 *Dest = (void *) &ieVectT
& && && && && &
& && &&&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& {
typedef u /* 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)/* 实际频率输出寄存器 */
/*可读写寄存器*/
#define&&MBRWRegAdd 0x009F20
/*读写寄存器
起始地址:0x009F20;
长度& & :0x10;
/*EEPROM寄存器*/
起始地址:0x009F30;
长度& & :0xCF;
#define&&MBEEPROMRegAdd 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 FunC
&&unsigned int RegA
&&unsigned int RegN
&&unsigned int Buf[128];
&&unsigned int S
&&unsigned int TxL
&&unsigned int RxL
&&unsigned int P
&&unsigned int TimeoutR
&&unsigned int TimeoutC
//--------------------供外部调用函数-------------------------------
extern struct MODBUSDATA ModbusM
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 char&&auchCRCHi[] = {
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 char&&auchCRCLo[] = {
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 ModbusM
// -------Modbus初始化----------0
void ConfigureModbus (void)
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.Point++];
& && && && &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(200;)
//设开关频率volatile int SwitchRate(1K~20K,单位为KHZ)
//设3.5字符时间为delay3.5 =(int)(3.5*10*1000/BtRate);
//计数器Timeout3.5=delay3.5*SwitchR
//---------------------------------------------
interrupt void ScibRxInt (void)& && &// SCI-B
PieCtrlRegs.PIEACK.bit.ACK9 = 1; //ACK复位
temp=ScibRegs.SCIRXBUF.
switch( ModbusModule.Status ){
&&case SEND_END:& && &//4
& &ModbusModule.Status = RECE_START;
& &ModbusModule.Point=0;
&&case RECE_START:& &&&//1
& &ModbusModule.Buf[ModbusModule.Point] =
& &ModbusModule.Point++;
& &ModbusModule.RxLen = ModbusModule.P
ModbusModule.TimeoutReg=0;
//---------------------------------------------
//&&程序第二部分:MODBUS 协议解析与构造
// 协议帧构造
// 协议帧解析
//---------------------------------------------
//---------------------------------------------
// 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 uI /* CRC循环中的索引 */
& & & & while (usDataLen--) /* 传输消息缓冲区 */
& & & & & & & & uIndex = uchCRCHi ^ *puchMsg++ ; /* 计算CRC */
& & & & & & & & uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
& & & & & & & & uchCRCLo = auchCRCLo[uIndex] ;
& & & & return (uchCRCHi && 8 | uchCRCLo) ;
}//uint16 crc16(uint8 *puchMsg, uint16 usDataLen)
//---------------------------------------------
// RTU Set N Hold Register
// CMD=16 SET_N_HLD_REG
// Constructe Answer Frame
//---------------------------------------------
void&&ModbusSlaveSetNHldRegAnswer ( Uint16 board_adr,Uint16 start_address,Uint16 lenth)
Uint16 i=0,j=0;
ModbusModule.Buf[i++] = board_
ModbusModule.Buf[i++] = SET_N_HLD_REG;
ModbusModule.Buf[i++] = WORD_HI(start_address);
ModbusModule.Buf[i++] = WORD_LO(start_address);
ModbusModule.Buf[i++] = WORD_HI(lenth);
ModbusModule.Buf[i++] = WORD_LO(lenth);
j=GetCRC16(ModbusModule.Buf,i);
ModbusModule.Buf[i++] = WORD_LO(j);
ModbusModule.Buf[i++] = WORD_HI(j);
ModbusModule.TxLen& & =
ModbusModule.Point& &= 0;
//---------------------------------------------
// RTU Read Hold Register
// CMD=03 READ_HLD_REG
// Constructe Answer Frame
//---------------------------------------------
void&&ModbusSlaveReadHldRegAnswer ( Uint16 board_adr,Uint16 *com_buf,Uint16 lenth)
Uint16 i=0,j=0;
ModbusModule.Buf[i++] = board_
ModbusModule.Buf[i++] = READ_HLD_REG;
ModbusModule.Buf[i++] = lenth&&1;
for(j=0;j&j++){
&&ModbusModule.Buf[i++] = WORD_HI( * (com_buf+j) );
&&ModbusModule.Buf[i++] = WORD_LO( * (com_buf+j) );
j=GetCRC16(ModbusModule.Buf,i);
ModbusModule.Buf[i++] = WORD_LO(j);
ModbusModule.Buf[i++] = WORD_HI(j);
ModbusModule.TxLen& & =
ModbusModule.Point& &= 0;
//---------------------------------------------
// RTU&&从站接收分析
// 3 READ_HLD_REG
// 16 SET_N_HLD_REG
// 返回值: 0&&OK
//& & 1 CRC校验错误
//& & 2 站号不匹配
//& & 3 读地址无效
//& & 4 16写地址不匹配
//& & 5 16写数据字数不匹配
//---------------------------------------------
Uint16 RTUSlaveFrameAnalyse (void)
Uint16&&*dest_p;
Uint16 crc_result, crc_
Uint16 RegN
int16&&RegA
crc_tmp&&= ModbusModule.Buf[ModbusModule.RxLen-1]&&8;
crc_tmp += ModbusModule.Buf[ModbusModule.RxLen-2];
crc_result=GetCRC16(ModbusModule.Buf,ModbusModule.RxLen-2);
if ( crc_tmp != crc_result )& && & // CRC 校验正确
& && &&&return 1;
if ( ModbusModule.ID != ModbusModule.Buf[0] )
& && &&&return 2;
ModbusModule.FunCode=ModbusModule.Buf[1];
RegAddr= (ModbusModule.Buf[2]&&8) + ModbusModule.Buf[3]-0x4000;
RegNum = (ModbusModule.Buf[4]&&8) + ModbusModule.Buf[5];
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);
& & //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[6])return 4;
& && && &dest_p=((Uint16*)(MBRRegAdd+RegAddr+RegNum-1));
& && && &for (i=0; i&ModbusModule.Buf[6]; i+=2)
& && && && &{
& && && && & *(dest_p + i/2) = ( ModbusModule.Buf[i+7]&&8 ) + ModbusModule.Buf[i+8];
& && && && &}
& && && &ModbusSlaveSetNHldRegAnswer(ModbusModule.ID,RegAddr,RegNum);& &
& & }//end switch
//---------------------------------------------
// ModbusRTUSlaveRun
// 通讯由主站发起,从站初始化为接收,并相应的做出回应。
// 站号在初始化中有设置,以后不再更改。
//---------------------------------------------
void ModbusRTUSlaveRun (void)
switch (ModbusModule.Status){
&&case IDLE_WAIT ://0
& &ScibRegs.SCITXBUF = ModbusModule.Buf[ModbusModule.Point++];
& &ModbusModule.TxLen--;
& &ModbusModule.Status = SEND_START;
&&case SEND_START ://3
& &asm(&nop&);
&&case SEND_END ://4
& &if (ModbusModule.TimeoutReg&=10)
& &{&&//超时10ms
& & //ModbusModule.ReTryTime++;
& & ModbusModule.TimeoutReg=0;
& & //InitSci_B(); //***********
&&case RECE_START ://1
& &if (ModbusModule.TimeoutReg&=5)
& &{&&//接收帧结束
& & ModbusModule.Status = RECE_END;
&&case RECE_END ://2
& &if(RTUSlaveFrameAnalyse()==0 )
& & {//帧解析正确
& &&&ModbusModule.Status =IDLE_WAIT;
& & {& && && & //帧解析不正确
& &&&ModbusModule.Status =SEND_END;
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
& & if (ScibTxFlag == true)
& & & & & & for(i = 0; i & 8; ++i)
& & & & & & {
& & & && & & & & & & & & & ScibRegs.SCITXBUF =& &&&// Send data
& & & & & & & & }
& & & & & & & & ScibTxFlag =
& & & & 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时执行这里
& && &&&LB _c_int00& && && &;Branch to start of boot.asm in RTS library//FLASH中执行这里
& & .endif
请教楼主:
我做毕业设计,就用到F2812的SCI和打印机相连,能用DSP控制打印机。大概就是打印出银行的排队小票。可以说说思路,现在还是不太理解从哪改起。我有PC机与SCI通信的实验例子,就是PC机向2812传一个字符。
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[400*80]& &可以编译通过
& && & A[400*100]& &编译出错
提示: 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吗?那样联系方便些。我做这个不久,需要阁下指点。谢谢。
我的QQ.验证写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怎么回事?
(原文件名: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;&&
EPwm1Regs.CMPA.half.CMPA=100;& && && && && && &//A的输出占空比
EPwm1Regs.CMPB=100;
EPwm1Regs.CMPA.half.CMPA=0;& && && && && && &//A的输出占空比
EPwm1Regs.CMPB=0;
就是这样的哈~
这个波形看上去很正常呀?你在后面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 = 0 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楼,你这个问题我暂时不清楚,有我空看一下手册
阿莫电子论坛, 原"中国电子开发网"

我要回帖

更多关于 c 编写modbus上位机 的文章

 

随机推荐