miller2 解码状态图手稿

来源:互联网 发布:古代人有多可怕 知乎 编辑:程序博客网 时间:2024/06/09 20:03


花了一天的时间啊,脑袋都闷闷的,终于有个手稿出来了

对时序协议,写状态图的原则,我总结如下:

1不可再分割

2步数只到当前这一步,不包括前面的一步,也不能包括后面的未知的一步,

3下一个状态,与当前状态之前的状态没有关系,不然的话你还得把之前的状态写出来

4以产生上升沿中断,为状态作图的切入点

5在一个完整的数据处,也还是会截断

6在考虑状态简化的时候,要考虑到,当前的状态是不是得不到数据,如果是得不到数据,其为1个状态,得到数据的还是一个状态

这两个状态就算形状很像,也必须要区分开来,因为状态本身代表着是不是得到数据这一信息在里面,不可忽视。


下面是手稿照片:




写完状态图之后,发现复习了一遍数字逻辑设计,大二学的,不错哈哈哈





可恶的是,每次上升沿,检测出来的值都太大了啊,怎么办呢?没法检测us级别的么,蛋疼啊

同学说是 接触不牢固,导致脉冲的不稳定

这个有可能,但是在我看来,不是最大的问题吧,至少我觉得还不是最大的问题哦 

但是是有可能的,!!

明天干嘛,明天要试试在外部写函数,来解码,而不是在中断里面,可以记录多少数据

在外面使用while循环,进行状态解码,最主要的是定多少个数


2使用定时器隔一段时见采样的方法,虽然有偏移,但是还是不失为一个好方法哦,哈哈

明天可以试试


3可以把两块板子的东西焊接到一起,来试验一下




进行时序检测的时候,来测试最小能够检测多少毫秒的数据

先把板子焊接起来,发送程序里面屏蔽一切中断,进行发送!3.125us的间隔的方波

接收程序里面,打印前100个接收到的数据的情况。看看数据就知道是不是接收正确了

没必要使用数据0,1打印过来看哦

或者在中断程序里面一直打印Uart0_Printf("rTCNTO0\n",)来观察情况。

同学用的接口是,GPB8 ,发送,

EINT7用来接收

已经焊接上

焊上了,还要把它重新弄掉,真是无语啊 ,自私自利的人那,哎重来不考虑别个在干嘛。

跟这样的自私的人合作,会有前途么,哎,这样的人不可以深交,不过这样的人老实,一般的没有触及核心利益的东西,表面的东西,会奉献的很无私

 

下一步的计划!!

1.注意,如果用Uart0_Printf()出来的数据差别太大,跟用示波器打出来的波形对不上,那就有两个问题

你波形发送端产生的波形是不是有?

还有就是你接收端的波形是不是也跟发送端的波形一致,如果不一致,那是肯定不行的,如果一致的话,才进行下一步的计划。

 

2上面的东西弄出来一致了,现在有一个问题打出来的波形,和printf出来的数据,比较相近了,但是现在的问题是,还是有差别

我用自己的主机发送的方波间隔是49us,按说实际检测到的中断在92us,左右,还是要有细微的差别。

 

3可以使用一个定时器,产生一个方波信号,这个方波信号作为我的中断源检测输出,看看打印出来的数据合不合法,如果合法的话,就开始焊接

但是比较局限的是,这个定时器,没法产生miller吗,只能唯一的产生方波信号,利用自动重载不需要系统来搞。

韦东山嵌入式群里面说了,自动重载属于AHB总线,不需要cpu来干涉,也就是不需要cpu指令,

这个说法,也就是说明了可以一边使用定时器产生中断,产生方波波形,然后再使用定时器进行计数,来整


在计算定时器的计算值的时候,不好忘记忽视,Uart0_Printf带来的误差,不然很不对的哦

下午想把在打印函数的延时考虑排除

具体做法如下

1使用定时器1作为PWM输出,定时器0作为捕获 外部中断9作为上升沿捕捉,整个程序只需要一个开发板

2当定时器1翻转的时候,那么其会自动重载,产生稳定的波形

3上升沿来临,外部中断9产生中断,在中断函数里面,使用一个数组记录产生中断时候的rTCNTO 数据

4记录了100次之后,屏蔽中断,尝试在外部主函数中打印出来中断,如果可以的话


现在问题是,在主函数里面打印不了中断,哎苦逼,晚上回来调试一下,先去打会篮球

板子连不上电脑 初步判断是因为串口线接触不良的问题  捣鼓捣鼓就好了哈

现在问题是打印不出来  恼火中


要产生中断,配置好中断初始化函数之外

外部中断的管脚也要配置好,不然容易出现问题,老是不容易找到

比如外部中断4

void   eint4_init(void)//GPF4{       rGPFCON &=~(0x3<<8);//GPF4作为miller2接收中断引脚        rGPFCON |=0x2<<8; //GPG4配置为外部中断                rINTMSK = ~(0x1<<4);//外部中断4_7允许      // rINTPND |=0x1<<4;//清除外部中断4_7      // rEINTPEND = (1<<4);//发生了外部中断的标志位,外部中断4清零       rEINTMASK = ~(1<<4); //允许外部中断4       rEXTINT0 &= ~(0x7<<16);       rEXTINT0|=0x5<<16;//上升沿触发       pISR_EINT4_7=(unsigned int)eint4_test;   }

不是rGPFCON |=0x2<<2,不然到死都产生不了中断啊,骚年



截止到0401下午3点钟,有了一些眉目,可以方波脉冲信号进行定时器计数了,方法如下;

1.使用到定时器0和定时器1,定时器0作为pwm输出,要配置好GPB0作为pwm输出管脚,定时器1作为定时计数,两个时钟源的配置是基本一致,相差不大的哦

2使用外部中断4,注意GPFCON的配置啊,如上面的代码,不然进入不了中断的吗

3定义全局变量data[1000]来存放每次进入中断的rTCNTO1的值,数据多了才具有统计意义吗

4在中断函数里面不要停止中断吗,一直计数,也不管它溢出,等计数到了800之后,把全局变量eint4_flag置为1

5在主函数里面,使用while(!eint4_flag)检查状态位,状态位变为1的时候,打印800个data数据出来

6注意,在班子上,现不要把TOUT0输出和EINT4引脚接到一起,等开关拨到NANDFlash之后,一段时间等到PWM输出声音稳定了之后,再使用杜邦线连接两个管脚

下面是主函数

 volatile unsigned int data[1000]; volatile  unsigned char eint4_flag=0; unsigned int j;int Main(){  unsigned long a = 1000000;unsigned char buf_miller[2]={0x6c,0xc2}; //0110 1100  0000 0010MMU_Init();//timer0_isrinit();eint4_init();//开启外部中断并允许外部中断Uart0_Init(115200) ;delay_TR();Uart0_Printf("uart init finished\n");              delay_TR();       Uart0_Printf("eint_init finished\n");              timer0_init();//pwm输出       delay_TR();       Uart0_Printf("timer0_Init finished\n");//IO_Init(); //管教配置,GPF1外部中断上升沿触发//GPB1发送miller码数据              timer1_init();//用来计数                 while(!eint4_flag);          for(j=0;j<800;j++)          Uart0_Printf("data[%d]=%d eint4_flag=%d\n",j,data[j],eint4_flag);   while(1);}

下面是中断函数

void __irq  eint4_test(void){        data[data_cnt++]=rTCNTO1;        rSRCPND = rSRCPND | (0x1<<4);        rINTPND = rINTPND | (0x1<<4);       if(rEINTPEND&(1<<4))              rEINTPEND = rEINTPEND | (0x1<<4);         if(data_cnt>800)               eint4_flag=1;                      //以上为清除外部中断4带来的中断标志}


这样就可以了哈,不要在中断函数里面把定时器关闭,中断屏蔽位置1

相应的文件时《《0401_可以对外部中断脉冲进行定时,但是问题是每个中断重复进入,为何.rar》》

问题又来了,记录的数据,除了在该进入中断的时候进入中断之外,会重复进入一个中断两次,不知道是什么原因,下面是波形



可以解决手拔插这个不好的习惯的方法如下:

一开始屏蔽外部中断9.当一切所需要的配置配置好的时候,延时一段时间,把屏蔽位清零

主函数如下:

int Main(){  unsigned long a = 1000000;unsigned char buf_miller[2]={0x6c,0xc2}; //0110 1100  0000 0010MMU_Init();     int_mask();//timer0_isrinit();eint9_init();//开启外部中断并允许外部中断Uart0_Init(115200) ;delay_TR();Uart0_Printf("uart init finished\n");              delay_TR();       Uart0_Printf("eint_init finished\n");              timer0_init();//pwm输出       delay_TR();       Uart0_Printf("timer0_Init finished\n");//IO_Init(); //管教配置,GPF1外部中断上升沿触发//GPB1发送miller码数据              timer1_init();//用来计数                        delay_TR();        delay_TR();        delay_TR();        int_allowed();                         while(!eint4_flag);          for(j=0;j<400;j++)          Uart0_Printf("data[%d]=%d eint4_flag=%d\n",j,data[j],eint4_flag);   while(1);}
其中 两个函数如下:

void  int_mask(void){       rINTMSK |= 0x1<<5;//外部中断8_23不允许       rEINTMASK |=1<<9; //允许外部中断9,不允许}void int_allowed(void){       rINTMSK = ~(0x1<<5);//外部中断8_23允许       rEINTMASK = ~(1<<9); //允许外部中断9}

这个函数屏蔽和开启,只是针对外部中断9而言,其他的可以重新修改,在eint9_init里面就不要开启或者屏蔽外部中断9了


快速中断的作用。能够提高中断的执行速度哈比如上面的重复进入中断的时间是200个定时器计数,即4us,使用快速中断后,重复进入中断的时间降低到了

150,即3us,显然中断执行之间提速了1us。

快速中断的使用方法是,以eint9为例,首先将INTMOD全部清零,然后将eint9对应的位置1,注意,只能有一个快速中断,所有程序只能有一个快速中断

载入中断处理函数的语句是:

 pISR_FIQ=(unsigned int)eint9_test;

整个eint9中断初始化的代码过程如下:

void   eint9_init(void){       rINTMOD &=~(0xffff);//先将int_mod 全部清除为0;       rINTMOD|=0x1<<5;//外部中断9设置为快速中断              rGPGCON &=~(0x3<<2);//GPG1外部中断9,据说有滤波器的功能       rGPGCON|=0x2<<2;//GPG1能够作为外部中断9             // rINTMSK = ~(0x1<<5);//外部中断8_23允许      // rEINTMASK = ~(1<<9); //允许外部中断9              rSRCPND |=(0x1<<5);       rINTPND |=0x1<<5;//清除外部中断8_23       rEINTPEND|=0x1<<9;//发生了外部中断的标志位,外部中断9清零                   rEXTINT1 &= ~(0x7<<4);       rEXTINT1|=0x5<<4;//上升沿触发 EINT9       rEXTINT1|=0x1<<7;//外部中断9允许滤波器功能              //pISR_EINT8_23=(unsigned int)eint9_test; //普通中断        pISR_FIQ=(unsigned int)eint9_test;//快速中断}

但是中断还是会重新进入,这是什么原因呢,我擦泪

晚上吃饭的时候想了一下,如果是硬件的原因,在下降沿来临的时候,因为是脉冲,会不会因为,由高电平,到低电平来的太快了

如果管脚和电感和电容相连接的话,那么会产生震荡,导致重新产生一个向上的脉冲,产生中断。?

有可能啊,因为这个震荡的时间是一定的,是4us,快速中断的时候是3us。

但是震荡为何会与中断的类型有关呢?这个不解啊


如果考虑焊接一个MSP430来作为PWM输出的话,可能速度跟不上,或者使用IO口模拟那个时序,

速度也不一定能够跟得上,而且程序,代码还得重新设计,考虑不一定能够合的来哦。


偶然间发现数据无重复,这是为什么呢!!这是为什么呢,哈哈哈哈哈哈

我懂了,你定义的数据位1000位的,等到你计数完,之后,又重头开始计数,那么你的值肯定跟上一次有重叠的部分

比如第一个是65535 ,第二个是65335,第三个是55535,第四个是45335

如果当你只重复计数一次的话,那么值就不会重复了,记住,当计数大于800的时候

屏蔽外部中断四,然后再主函数里面打印这些值,你会发现很有规律吧,哈哈哈哈哈

没有重复,坚决没有,下面是上图。


下面就可以开始解码了哈,不用那么蛋疼了哦