m序列是最长线性移位寄存器序列的简称。它是由带线性反馈的移存器产生的周期最长的序列。一般来说,一个n级线性反馈移存器可能产生的最长周期等于(2^n -1)。
m序列是一种典型的伪随机序列。在通信领域有着广泛的应用,如扩频通信、卫星通信的码分多址(CDMA),数字数据中的加密、加扰、同步、误码率测量等领域。
rand函数,C语言中用来产生一个随机数的函数。rand函数界限:stdlib.h头文件中有宏#define RAND_MAX 0x7fff, rand产生一个0-0x7fff的随机数,即最大是32767的一个数。
由于应广这种单片机资源有限,因此不支持这种stdlib.h这种库,但如果又要用到随机数怎么办呢,那就自己实现一个了。也不复杂。
不多说,上代码。
#include"extern.h"
/*调试输出开关,关闭之后测试端口不输出了*/
#define DEBUG
/*1m 标记*/
bit msFlag;
/*us计数*/
byte ucUsCnt;
/*ms 计数*/
byte ucMsCnt;
WordReload_T16;
/*可以用示波器观察对应端口*/
#ifdef DEBUG
bit US100_OUT :pa.7
bit MS_OUT :pa.6
bit MS10_OUT :pa.0
#endif
/*中断服务程序*/
void Interrupt(void)
{
pushaf;
if(Intrq.T16)
{
STT16Reload_T16;
Intrq.T16 = 0;
ucUsCnt++;
if(ucUsCnt>9)
{
ucUsCnt=0;
/*100us*10=1ms*/
msFlag=1;
}
/*100u task,紧急任务放这边,但这里的任务尽量少,
心脏部位,尽量减少干扰,需要保证tick精准*/
#ifdef DEBUG
if(US100_OUT)
{
US100_OUT=0;
}
else
{
US100_OUT=1;
}
#endif
}
popaf;
}
/*T16设置*/
Void Timer16_Init(void)
{
/*向上计数 1600就发生中断 1600/16M=0.0001s=100us,理论设计*/
//Reload_T16 = 32768 - 1600;
/*根据测算(示波器校准),除去误差(约为20个sysclk周期),设置1580这个值可能更准确,
SYSCLK越快,误差越小.从进入中断开始,到重新设置计数器,中间大概需要20个sysclk周期*/
Reload_T16 = 32768 - 1580;
/*设置计数器值*/
STT16Reload_T16;
/*配置T16 控制寄存器*/
$ T16MIHRC,/1,BIT15;
INTRQ.T16 = 0;
INTEN.T16 = 1;
msFlag=0;
ucUsCnt=0;
}
eword ueMregInit;
byte ucFb;
#if 0
/*级数20-4000011*/
/*0b000_000_000_000_000_000_001_001反馈系数*/
#endif
void InitRand(void)
{
ueMregInit=0x012345;/*初始化,种子*/
if(!ueMregInit)
{
ueMregInit=0x012345;
}
}
/*20bit m序列,级数20-4000011*/
void Rand20(void)
{
ucFb=0;
if(ueMregInit$0.0)
{
ucFb++;
}
if(ueMregInit$0.3)
{
ucFb++;
}
ueMregInit>>=1;
if(ucFb.0)
{
ueMregInit$2.3=1;
}
else
{
ueMregInit$2.3=0;
}
}
voidFPPA0 (void)
{
.ADJUST_ICSYSCLK=IHRC/2,IHRC=16MHz,init_ram;
byte ucCnt;
byte ucTmp;
eword ucLpcnt=0;
/*开启看门狗*/
CLKMD.En_WatchDog = 1;
wdreset;
/*初始化T16*/
Timer16_Init();
/*设置一个20bit的种子*/
InitRand();
#ifdef DEBUG
$ US100_OUT out,low;
$ MS_OUT out,low;
$ MS10_OUT out,low;
#endif
Engint;
while (1)
{
/*喂狗*/
wdreset;
/*m序列运算 20bit长度,需要新的值,调用一次就行*/
Rand20();
/*可以打开查看输出指,但是会影响正常时许*/
//.printf("rand=0x%x\n",ueMregInit);
ucLpcnt++;
if(ucLpcnt==1048575)
{
/*一个周期,可以看到数据恢复到inti值*/
ucLpcnt=0;
}
/*1ms标记*/
if(msFlag)
{
ucMsCnt++;
if(ucMsCnt>9)
{
/*1ms*10=10ms*/
ucMsCnt=0;
/*10mstask 放这里*/
#ifdef DEBUG
if(MS10_OUT)
{
MS10_OUT=0;
}
else
{
MS10_OUT=1;
}
#endif
wdreset;
}
/*1ms task*/
#ifdef DEBUG
if(MS_OUT)
{
MS_OUT=0;
}
else
{
MS_OUT=1;
}
#endif
msFlag=0;
}
}
}