当前位置:首页 > 解码
  • 示波器解码,你真的了解吗?

    示波器解码,你真的了解吗?

    什么是协议解码?它有什么作用?协议解码是示波器非常实用的功能,很多工程师因为不熟悉操作,或者参数设置不正确,最终没有得到理想的结果。本文对解码设置方面的几个细节做一个介绍,帮助您快速上手示波器的协议解码。 一、解码 解码是一种用特定的计算方法,将电脉冲信号、光信号、无线电波等转换成它所代表的信息、数据等的过程。解码是受传者将接受到的符号或代码还原为信息的过程,与编码过程相对应,不同的解码方法就是不同的协议,而示波器,示波器经过多年的发展,早已可以直接将波形数据解码后以十六进制,十进制或者字符的形式呈现出来,而且可以兼容非常多种类的协议。 二、采样率 第一个需要关注的要点就是采样率,示波器是根据采集来的波形数据进行解码。如果波形采集的实时采样率不足,则可能对解码结果造成影响。ZDS4054Plus示波器标配512M存储深度,可以充分保证长时间捕获波形的高采样率。毕竟只有捕获了正确的波形,才能得到正确的解码。 三、协议参数设置 协议参数设置是解码成功中最重要的一环,不同的设置可能解码结果不一样,或者导致无法解码,实际应用时,有一半情况是因为忽略了一些设置而导致解码出错。 首先是要选择正确的协议类型,并将“触发使能”选择“ON”,信号将按照协议的开始位、数据位或地址位等进行触发。 其次是参数的设定,可以通过点击“协议参数”进入相应的参数设置,根据不同的需要设置相应的参数,同时注意查看下方“触发设置”是否与预先设定的方式一致。 四、阈值设置 阈值设置是平时解码中最容易忽略的一点,示波器对波形进行解码时,需要有参考的基准线,示波器对比波形数据相对于基准线的值来判断高低电平,一般示波器默认阈值是自动阈值,即最大值和最小值之间的中间值来自动确认的,比如,CAN-H电平是3.5V,CAN-L电平是1.5V,如果屏幕内只有CAN-H和CAN-L,那么阈值就是2.5V,此时可以很好的识别出高低电平,如果屏幕内的波形是从-3.5V开始,然后触发出CAN信号,那么阈值就是OV,此时候CAN-L也会被识别为高电平,从而导致解码错误。所以当屏幕内高低电平有一个偏离特别大时,可能需要手动设置阈值。 帧的完整性 有的时候,屏幕内抓到的波形可能不是一个完整的帧,所以导致示波器无法完成解码,可以尝试将时基放大,在一个屏幕内抓多个帧进行解码,保证屏幕中有至少一个完整的帧。以上就是示波器的几个知识点,希望能给大家帮助。

    时间:2020-05-22 关键词: 解码 示波器 波形

  • 51单片机解码PPM波

    先说说PPM波,从图上可以看出周期为20ms,冠丽控实际是6通控,但预留两通没有使用。通道的高电平区间为0.765~1.6ms 低电平时间为0.395ms引导波形的高电平 时间为10.165ms。我的单片机是 11.0592MHZ 这样算的话, 显示的值 应该是 706 到 1491 之间,中立位为 1100正好和理论值相符。这里在提点单片机相关的知识,51单片机是低电平触 发中断,我这里用的是while(int0==0)来等待高电平 的到来。不知道这样做是否合理,不过实践看来还是可以的。明说一点,程序中 LCD* 都在1602.h文件中,自己加个1602的头文件即可。下面是程序的主要部分#include #include "1602.h"unsigned char channel=0,i=0;unsigned int xdata PPM_channel1[10],PPM_channel2[10],PPM_channel3[10],PPM_channel4[10],PPM_channel5[10],PPM_channel6[10];bit Timer0_OverFlowFlag=0;//定时器0的溢出标志,如果溢出,则有问题;unsigned char qian,bai,shi,ge;void DepartNum(unsigned int temp) ;unsigned int filter(unsigned int *s); //这不函数的作用?void delay(unsigned int k){unsigned int i,j;for(i=0;i

    时间:2018-11-30 关键词: 解码 51单片机 ppm波

  • 什么是BMP 的编码与解码

    bmp的解析:                 bmp的解析比较简单,参考bmp的文件格式几个正确的将bmp文件解析出来,只是要注意:每一扫描行的字节数必需是4的整倍数,也就是DWORD对齐的。如果你想确保图像的扫描行DWORD对齐可使用下面的代码:(((width*biBitCount)+31)>>5)<<2。bmp的编码:                  对于24位bmp编码难度不大,因为没有调色板,所以直接将内存内的像素值按bmp的文件格式写入即可。                 对于8位bmp编码,主要的困难是产生调色板,调色板有了,直接将数据区的像素定位到调色板的像素即可。调色板的生成主要有两步:一 分别取rgb的高四位(或5位),合并为一个word,对图像的每个像素都如此处理。二 参见聚类算法的K-MEANS算法对处理过后的图像数据处理取得调色板和图像像素在调色板中的index。细说下第二步:由于第一步的处理,图像像素最多覆盖2的(4*3)次方个色,即4096,统计这4096色在图像出现的次数;将这4096色按是用次数排序;统计使用的颜色,次数大于0为是用过;将前256色(使用的颜色》256)写入调色板;图像中的像素的index是该像素与调色板中的像素差距最小的那个。C++ 代码如下void writeOut8Bit(unsigned char *data)  {  // 调色板(54为文件头的大小)  unsigned char* colorPlate = data+54;  // 数据区  unsigned char* indexData  = data+bfOffBits; /*********************** 取得调色板与数据区的内容 ***********************/ // 取每个像素点的高iBit位进行处理,这样丢掉地位的值  int iLength    = biWidth * biHeight;  unsigned short* pColorData = new unsigned short[iLength];  int iBit       = 4;  int i,iRed,iGreen,iBlue; for(i=0; i>iBit;    iGreen = imageData[i].rgbGreen>>iBit;    iBlue  = imageData[i].rgbBlue>>iBit;    pColorData[i] = (unsigned short)((iRed<<(iBit*2)) + (iGreen0)     iUsedColor++;  } // 根据覆盖颜色是用的次数排序,冒泡排序  bool flag;  COLORCOVER tmp;  int j;  for(i=1; ifalse;    for(j=0;jif(colorCover[j].usedTimes < colorCover[j+1].usedTimes){      tmp = colorCover[j];      colorCover[j]   = colorCover[j+1];      colorCover[j+1] = tmp;      flag = true;     }    }    if(!flag){     break;    }  }  // 前256色即是调色板的内容  for(i=0; i<256; i++){    int tmp = i*4;    colorPlate[tmp]   = (unsigned char)((colorCover[i].colorIndex & 0xf)>iBit & 0xf)>(iBit*2)) tmp1)                  {                      tmp = tmp1;                      colorIndex = j;                  }              }              index[colorCover[i].colorIndex] = colorIndex;          }      }  // 生成数据区  int iLineData = ((biWidth * biBitCount + 31) & ~31) >> 3;  for(i=0; iint tmp = biWidth * (biHeight -1 - i);    for(j=0; jmageData图像的rgba值;biBitCount  图像位数,此为8;biWidth,biHeight是图像的宽,高;Square 是计算两像素的平方差的函数。           对于4位bmp的生成类似8位bmp.           对于1位bmp,调色板只有两个色:白色和黑色。对于图像的每个像素,(r+g+b)/3>128?白色:黑色。

    时间:2018-11-13 关键词: 解码 编码 bmp

  • STM32学习笔记:gps两种解码的方式

    做为现在的物联网行业,手持设备中,缺少不了的就是GPS定位功能。GPS模块和STM32的串口进行通信,将GPS的数据发送给M3的串口,由M3进行GPS协议的解码。解析出来后保存在响应的结构体中。在进行显示。这里分别介绍2中解析协议的方法,第一种就是自己写解析协议函数,第二种便是采用别人写好的GPS解析协议库:NMEALIB库,将这个库移植到M3中,直接调用API函数,就可以解析出GPS信息,同样的也保存在一个结构体中。下面分析一下这两种解析协议的算法,第一种,采用的是正点原子写的GPS解析算法(感谢原子哥)//从buf里面得到第cx个逗号所在的位置//返回值:0~0XFE,代表逗号所在位置的偏移.//0XFF,代表不存在第cx个逗号u8NMEA_Comma_Pos(u8*buf,u8cx){u8*p=buf;while(cx){if(*buf=='*'||*buf'z')return0XFF;//遇到'*'或者非法字符,则不存在第cx个逗号if(*buf==',')cx--;buf++;}returnbuf-p;//返回差值,}1234567891011121314从GPS中得到的一串数据是这样的:GPRMC,083559.00,A,4717.11437,N,00833.91522,E,0.004,77.52,091202,,,A?57因此,我们可以调用这个函数,得到第几个逗号所距离第一个字符的位置,例如:NMEACommaPos(buf,2),我们的到的是,第二个逗号距离的位置,也就是17//m^n函数//返回值:m^n次方.u32NMEA_Pow(u8m,u8n){u32result=1;while(n--)result*=m;returnresult;}12345678这个就不用多说了,都看的懂,//str转换为数字,以','或者'*'结束//buf:数字存储区//dx:小数点位数,返回给调用函数//返回值:转换后的数值intNMEA_Str2num(u8*buf,u8*dx){u8*p=buf;u32ires=0,fres=0;u8ilen=0,flen=0,i;u8mask=0;intres;while(1)//得到整数和小数的长度{if(*p=='-'){mask|=0X02;p++;}//是负数if(*p==','||(*p=='*'))break;//遇到结束了if(*p=='.'){mask|=0X01;p++;}//遇到小数点了elseif(*p>'9'||(*pslmsg[slx].azideg=NMEA_Str2num(p1+posx,&dx);//得到卫星方位角elsebreak;posx=NMEA_Comma_Pos(p1,7+j*4);if(posx!=0XFF)gpsx->slmsg[slx].sn=NMEA_Str2num(p1+posx,&dx);//得到卫星信噪比elsebreak;slx++;}p=p1+1;//切换到下一个GPGSV信息}}1234567891011121314151617181920212223242526272829303132333435这个便是解析GPGSV信息,GPGSV协议如下://分析GPGGA信息//gpsx:nmea信息结构体//buf:接收到的GPS数据缓冲区首地址voidNMEA_GPGGA_Analysis(nmea_msg*gpsx,u8*buf){u8*p1,dx;u8posx;p1=(u8*)strstr((constchar*)buf,"$GPGGA");posx=NMEA_Comma_Pos(p1,6);//得到GPS状态if(posx!=0XFF)gpsx->gpssta=NMEA_Str2num(p1+posx,&dx);posx=NMEA_Comma_Pos(p1,7);//得到用于定位的卫星数if(posx!=0XFF)gpsx->posslnum=NMEA_Str2num(p1+posx,&dx);posx=NMEA_Comma_Pos(p1,9);//得到海拔高度if(posx!=0XFF)gpsx->altitude=NMEA_Str2num(p1+posx,&dx);}123456789101112131415

    时间:2018-11-09 关键词: GPS 解码 STM32

  • Base64编码解码C语言实现

    static const char *codes =  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const unsigned char map[256] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255, 255, 254, 255, 255, 255,   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255, 255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }; int base64_encode(const unsigned char *in,  unsigned long len,                          unsigned char *out) {    unsigned long i, len2, leven;    unsigned char *p;    /* valid output size ? */    len2 = 4 * ((len + 2) / 3);    p = out;    leven = 3*(len / 3);    for (i = 0; i < leven; i += 3) {        *p++ = codes[in[0] >> 2];        *p++ = codes[((in[0] & 3) << 4) + (in[1] >> 4)];        *p++ = codes[((in[1] & 0xf) << 2) + (in[2] >> 6)];        *p++ = codes[in[2] & 0x3f];        in += 3;    }    /* Pad it if necessary...  */    if (i < len) {        unsigned a = in[0];        unsigned b = (i+1 < len) ? in[1] : 0;        unsigned c = 0;        *p++ = codes[a >> 2];        *p++ = codes[((a & 3) << 4) + (b >> 4)];        *p++ = (i+1 < len) ? codes[((b & 0xf) << 2) + (c >> 6)] : '=';        *p++ = '=';    }    /* append a NULL byte */    *p = '';    return p - out; } int base64_decode(const unsigned char *in, unsigned char *out) { unsigned long t, x, y, z; unsigned char c; int g = 3; for (x = y = z = t = 0; in[x]!=0;) { c = map[in[x++]]; if (c == 255) return -1; if (c == 253) continue; if (c == 254) { c = 0; g--; } t = (t<*outlen) { return CRYPT_BUFFER_OVERFLOW; } out[z++] = (unsigned char)((t>>16)&255); if (g > 1) out[z++] = (unsigned char)((t>>8)&255); if (g > 2) out[z++] = (unsigned char)(t&255); y = t = 0; } } // if (y != 0) { // return -1; // } return z; }Base64编码基本上理解为:将二进制数据转变为可见的ASCII码字符串(反之亦然)。这个很有用,比如向数据库里面写东西,如果是二进制(如图片)的话,转变成字符串就会很方便的存入。该编码的好处是:速度快,编码为ASCII码后体积增加三分之一左右。

    时间:2018-10-10 关键词: 解码 编码 语言 c base64

  • 解码labview读写二进制文件格式

    一直觉得NI很恶心,最近越发觉得恶心,竟知道骗钱,我花了2周去探它该死的数据格式,问他们售后居然说不知道...还得我亲自动手...现在把数据格式写下来,为大家做点贡献吧...关于用matlab/vc读二进制文件 write to binary file的数据NI可以直接用这个函数把数据写下来,但是读取格式不告诉你,要你用它的软件去读...读的方法:1) 用uchar去读,将数据转置存储;2)用浮点去读,倒序;--------这些在网上可以查到,下面才是关键.... 对64位数据:3)每个通道有21个数据是头文件,即21*64bit的头信息,可以不去管它,跳过; 4)除了头文件外,每个通道还有1-3个字节的信息(不知道什么玩意儿),要跳过;具体来讲是这样,如果有6个通道,第一个通道存储了1个字节,要扣除;第2,4,5个通道多了2个字节,要扣除;第3,6通道多了3个字节要扣除.但是必须从3开始扣.即假如总共N字节数据,则第一个通道读N-3个,接下来2,4,5要读N-4个,剩下的3,6要读N-5个.只有这样才能正确的读取.不过要注意数据倒序的问题,实际的数据可能正好通道顺序相反.5)剩下的就是编程的问题了,还有很多细节大家可以自己解决,再看怎么要内存最小,耗时最短...我是没有在NI的说明文档里面找对相关的数据存储格式,这里是6个通道的举例,要是5个通道又得慢慢试了...再来一句,NI真恶心,其实没必要保留数据格式...搞的人家都要用它的软件...

    时间:2018-10-09 关键词: LabVIEW 解码 文件格式 读写二进制

  • 在小尺寸DSP上实现2D条形码解码

    在小尺寸DSP上实现2D条形码解码

    条形码一般被用于将关键的字母数字信息转换为数字系统能够扫描和读取的符号信息,而无需每次都要将信息录入数字系统。1D(一维)条形码只能对数字数据进行编码,在过去二十年中主要用于产品运输和追踪、系统安全、超市等场合。使用2D(二维)条形码,数据在水平和垂直方向被编码为2D符号,如下图1所示。2D符号所能包含的数据量远大于1D符号。2D条形码解决方案可比传统1D条形码提供更大的信息密度,特别是对于那些需要对精密信息而不是简单的码信息进行编码的应用。2D条形码技术的一些应用包括产品标签、产品信息追踪和检验、移动安全、出入境检查服务、医疗保健和电子商务等。图1:2D条形码示例。如今存在很多2D条形码算法,这催生出采用不同条形码技术的一系列应用。一般来说,有两种类型的2D条形码:1) 堆叠式2D条形码,例如PDF417和Code 49,2) 矩阵式条形码,例如QR码和数据矩阵。在这篇文章中,我们仅限于讨论数据矩阵式条形码技术[2]。2D数据矩阵式条形码技术2D数据矩阵式条形码包括在正方形或长方形中排列的黑色和白色模块,如图1所示。编码数据位映射到黑色和白色模块(或单元)组成的区域,称为数据区域。关于2D数据矩阵式条形码所支持的不同类型的编码方案的详细信息,请参见参考文献[2]。数据区域由定位图形包围(定位图形的底部和左侧只包含黑色模块,而定位图形的上部和右侧由交替的白色和黑色模块组成)。数据矩阵2D条形码支持由排位图形分隔的多个数据区域,从而能容纳更多数据信息。有两种版本的数据矩阵,一种是基于循环冗余校验(CRC)和卷积纠错,另一种是基于里德所罗门(RS)纠错。对于扫描、读取和提取数据位,基于CRC与基于RS的数据矩阵解码没有区别。提取数据位之后,基于CRC的解码与基于RS的解码路径不同,因为它们的交织和纠错方法不同。

    时间:2018-09-26 关键词: 解码 嵌入式处理器 小尺寸 dsp芯片 2d条形码

  • 实验9 红外接收单片机解码

    1.实现对红外遥控器的解码,并用其实现一些简单的控制/******************************************************************************** lcd1602显示遥控器接p3.2 * ** 按下上面的按键分辨显示遥控器上面的按键数据 * ** 连接方法:使用红外功能时 J1跳线短接 * *********************************************************************************/#include #include #define uchar unsigned char#define uint unsigned intuchar code Number[]="0 /1 /2 /3 /4 /5 /6 /7 /8 /9 ";uchar Order[]="switch/mode /quiet /start /< /> /eq /vol- /vol+ /rpt /u/sd ";#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};void delay_140us(uchar x); //x*0.14MSvoid delay1(int ms);void beep();sbit IRIN = P3^2; //红外接收器数据线sbit BEEP = P1^5; //蜂鸣器驱动线sbit RELAY= P1^4; //继电器驱动线uchar IRCOM[7];sbit LCD_RS = P2^6; sbit LCD_RW = P2^5;sbit LCD_EN = P2^7;uchar code cdis1[]={" Red Control "};uchar code cdis2[]={"IR-CODE:"};/*******************************************************************//* *//*检查LCD忙状态 *//*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。 *//* *//*******************************************************************/bit lcd_busy(){ bit result; LCD_RS =0; LCD_RW =1; LCD_EN =1; delayNOP(); result =(bit)(P0&0x80); LCD_EN =0; return(result);}/*******************************************************************//* *//*写指令数据到LCD *//*RS=L,RW=L,E=高脉冲,D0-D7=指令码。 *//* *//*******************************************************************/void lcd_wcmd(uchar cmd){ while(lcd_busy()); LCD_RS =0; LCD_RW =0; LCD_EN =0; _nop_(); _nop_(); P0 = cmd; delayNOP(); LCD_EN =1; delayNOP(); LCD_EN =0;}/*******************************************************************//* *//*写显示数据到LCD *//*RS=H,RW=L,E=高脉冲,D0-D7=数据。 *//* *//*******************************************************************/void lcd_wdat(uchar dat){ while(lcd_busy()); LCD_RS =1; LCD_RW =0; LCD_EN =0; P0 = dat; delayNOP(); LCD_EN =1; delayNOP(); LCD_EN =0;}/*******************************************************************//* *//* LCD初始化设定 *//* *//*******************************************************************/void lcd_init(){ delay1(15); lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据 delay1(5); lcd_wcmd(0x38); delay1(5); lcd_wcmd(0x38); delay1(5); lcd_wcmd(0x0c); //显示开,关光标 delay1(5); lcd_wcmd(0x06); //移动光标 delay1(5); lcd_wcmd(0x01); //清除LCD的显示内容 delay1(5);}/*******************************************************************//* *//* 设定显示位置 *//* *//*******************************************************************/void lcd_pos(uchar pos){ lcd_wcmd(pos |0x80); //数据指针=80+地址变量}/*******************************************************************/main(){ uchar m; IRIN=1; //I/O口初始化 BEEP=1; RELAY=1; delay1(10); //延时 lcd_init(); //初始化LCD lcd_pos(0); //设置显示位置为第一行的第1个字符 m =0; while(cdis1[m]!='') { //显示字符 lcd_wdat(cdis1[m]); m++; } lcd_pos(0x40); //设置显示位置为第二行第1个字符 m =0; while(cdis2[m]!='') { lcd_wdat(cdis2[m]); //显示字符

    时间:2018-09-17 关键词: 解码 单片机 红外接收

  • 让音乐播放更简单——Adafruit Music Maker FeatherWing和Audio FX Sound Board评测

    让音乐播放更简单——Adafruit Music Maker FeatherWing和Audio FX Sound Board评测

    本文介绍的两款模块都很小巧,但功能强大,一款是高集成度的OGG播放器方案,另一款是大家都熟悉MP3解码方案。 此次评测的是Adafruit的两块板子:Audio FX Sound Board & Music Maker FeatherWing w / Amp: Audio FX Sound Board 这是Audio FX Sound Board,主芯片是VSLI VS1000D,外围芯片是华邦的25Q128FV。有两排2.54排针接口,一个Micro USB接口,还有一个3.5mm耳机插座。背面还预留一个电源插座焊盘。 这是一个无需编程的可独立工作的小型音效触发器,定位与MP3音乐播放模块不同,比起一般的ISD芯片和可录音贺卡效果要好得多,大小22mmX48mmX6mm,重量4.7g,特别适用于道具、服装和玩具上。 供电是3V到5.5V直流,内建16MB存储,可插入电脑以U盘形式访问内部,支持OGG和WAV音频文件,支持44.1KHz,16bit(CD音质),11个触发输入,可触发播放对应的音频文件,立体声线路输出,可接耳塞或者有源音箱,五种触发效果(通过文件名设定)。 模块内置的固件设计了五种常用的触发效果,以方便在不同的应用场合下使用,分别是: 1. 基本触发:输入低电平时,触发一次播放; 2. 保持循环触发:当输入电平一直为低时,循环播放,松开即停; 3. 锁定循环触发:每按一次按键就开始重复播放,直到下一次按下按键; 4. 顺序播放:支持最多10段音频,第一次按键播放#0,第二次播放#1,如此类推,直到播放完#9后,又从#0开始; 5. 随机播放:与顺序播放类似,只是播放次序是随机的; 现在试试这些触发模式。首先准备一些音频文件,OGG格式或WAV。这几个文件需要与板子开关输入相对应,也就是一个IO可以触发一个文件或一系列文件的播放。总共有11个IO输入(板子一排从0到10编号)。每一个文件的触发播放的方式由它的文件名说明,触发方式和触发IO可以自由组合,例如: l T00.OGG,由IO0触发,基本触发方式; l T01HOLDL.OGG,由IO1触发,保持循环触发方式; l T02LATCH.OGG,由IO2触发,锁定循环触发方式; l T03NEXT0.OGG到T03NEXT9.OGG,由IO3触发,这10个文件按顺序播放; l T04RAND0.OGG到T04RAND9.OGG,由IO4触发,这10个文件随机播放; 我的测试硬件如下:绿色的是6个轻触开关(低电平有效);黄色的是移动电源,给模块供电;黑色的是一个有源音箱(用耳机也没有问题,驱动能力足够)。 这里稍感不便的是,U盘拷贝数据的速度只有19.8KBps。 假如按键触发方式还是不能满足实际需要,这个板子还提供了UART接口控制的进阶功能,可以实现更复杂的播放控制。有相应的Arduino Library可供使用: 值得注意主芯片VS1000D具有以下特性: OGG格式音频播放器SOC; 低功耗,带电源按键输入管脚,软件控制电源关断; 内建电压调整器,单电源输入; NAND FLASH接口; USB FS硬件接口; 内建高品质立体声DAC,集成耳放; 自带功能完整的播放器固件,也可以通过外部NAND FLASH或者SPI存储器修改或取代;因此,这个模块实际上是可以重新编程的,官网有这方面的的资料:http://www.vlsi.fi/fileadmin/app_notes/guide_vs1000.pdf,还有IDE免费下载:http://www.vlsi.fi/en/support/software/vside.html,这里不作详细说明。 多样的存储器接口,功能完整的固件,集成耳放和电源管理,USB免驱,低功耗,非常适合作为低成本的音乐播放器(还有USB大容量存储和USB音频设备)或者作为嵌入到其他物品上: Music Maker FeatherWing w / Amp 此Arduino模块虽小,但附带2.1W的D类功放(TI TPA2012D2),主芯片为VSLI VS1053,可以解码多种格式,比如MP3, AAC, Ogg Vorbis, WMA, MIDI, FLAC, WAV (PCM and ADPCM),并且支持高音、低音和音量的数字调节。 通过SPI接口,可以从SD卡中播放音频文件。特别的是,可以让芯片启动到MIDI模式,从UART 管脚读取31250波特的MIDI数据,以实现类似合成器和电子鼓的功能。[!--empirenews.page--] 用VS1053做MP3的例子非常多,而我这里选择另一方面的应用:MIDI模式。这个模块要使用MIDI模式,需要把PCB背面的跳线焊盘短路。模块需要两组电源5V和3V,分别供电给功放和VS1053。我这里从一个开发板上取电。功放输出外接两个无源小音箱(TB拆机件)。这里选择用电脑串口发送指令,USB转串口模块是必须的,强烈建议使用FT232,其他的像PL2303不一定正常。因为都是从USB取电,所以这里串口模块仅连接一根线。 这里参考了Adafruit的Arduino代码,用Python实现同样的功能,实现了这几个函数: 初始化函数(注意这里设置了两个通道,使用不同的乐器,在播放《献给爱丽丝》的时候使用两种乐器轮流演奏) def vs1053_midi_setup(com_name,timeout=0.5): ser=serial.Serial(com_name,31250,timeout=timeout)#31250 ser.open print(ser.name+' is opened!') midiSetChannelBank(ser,0, VS1053_BANK_MELODY) midiSetChannelVolume(ser,0, 127) instrument = VS1053_GM1_Acoustic_Grand_Piano #instrument = random.randint(1,128) midiSetInstrument(ser,0, instrument) print("Set Instrument1: %u"%instrument) instrument = VS1053_GM1_Acoustic_Guita midiSetInstrument(ser,1, instrument) print("Set Instrument2: %u"%instrument) print('Ready!') return ser 设置通道的乐器 def midiSetInstrument(ser, chan, inst): if chan>15: return -1 inst=inst-1 #page 32 has instruments starting with 1 not 0 :( if inst>127: return -1 ser.write([MIDI_CHAN_PROGRAM | chan]) time.sleep(1) ser.write([inst]) time.sleep(1) return 0[!--empirenews.page--] 设置通道音量 def midiSetChannelVolume(ser,chan,vol): if chan>15: return-1; if vol>127: return-1; ser.write([MIDI_CHAN_MSG | chan]) ser.write([MIDI_CHAN_VOLUME]) ser.write([vol]) return 0 设置通道 def midiSetChannelBank(ser,chan,bank): if chan>15: return -1 if bank>127: return -1 ser.write([MIDI_CHAN_MSG | chan]) ser.write([MIDI_CHAN_BANK]) ser.write([bank]) return 0 激发音符 def midiNoteOn(ser, chan, n, vel): if chan>15: return-1; if n>127: return-1; if vel>127: return-1; ser.write([MIDI_NOTE_ON | chan]) ser.write([n]) ser.write([vel]) return 0 停止音符 def midiNoteOff( ser, chan, n, vel): if chan > 15: return -1; if n > 127: return -1; if vel > 127: return -1; ser.write([MIDI_NOTE_OFF | chan]) ser.write([n]) ser.write([vel]) return 0 停止所有音符 def midiNoteAllOff( ser, chan): if chan>15: return -1 ser.write([MIDI_CHAN_MSG | chan]) ser.write([MIDI_NOTE_ALL_OFF]) ser.write([0x7b]) ser.write([0x7c]) ser.write([0x7d]) return 0[!--empirenews.page--] 播放一串变化的音符(Adafruit演示程序) def test_play_loop( ser, looptime ): print("===Music Start===") while looptime>0: i=60 while i<69: midiNoteOn(ser,0, i, 127); time.sleep(0.1) midiNoteOff(ser,0, i, 127); i=i+1 time.sleep(1) looptime=looptime-1 ser.close() print("===Music End ===") 以下为实现播放《献给爱丽丝》的代码: 定义音符 A2=0 #220Hz B2 = 1 H2 = 2 C2 = 3 Cis2= 4 D2 = 5 Dis2 = 6 E2 =7 F2 =8 Fis2 =9 G2 =10 Gis2 = 11 A3 =12 #440Hz B3 =13 H3 =14 C3 =15 Cis3 = 16 D3 =17 Dis3 = 18 E3 =19 F3 =20 Fis3 =21 G3 =22 Gis3 = 23 A4 =24 #880Hz B4 =25 H4 =26 C4 =27 Cis4 = 28 D4 =29 Dis4 = 30 E4 =31 F4 =32 Fis4 =33 G4 =34 Gis4 = 35 A5 =36 #1760Hz B5 =37 H5 =38 C5 =39 Cis5 = 40 D5 =41 Dis5 = 42 E5 =43 F5 =44 Fis5 =45 G5 =46 Gis5 = 47 A6 =48 #3520Hz B6 =49 H6 =50 C6 =51 Cis6 = 52 D6 =53 Dis6 = 54 E6 =55 EoS = 255 #End of score en =128 #End of line flag[!--empirenews.page--] 《献给爱丽丝》的乐谱: #8ms每单位 #For Elise (3/8, 60bpm) tone=[ 120, 0, E5|en, 150, 0, Dis5|en, 180, 0, E5|en, 210, 0, Dis5|en, 240, 0, E5|en, 14, 1, H5|en, 44, 1, D5|en, 74, 1, C5|en, 104, 1, A5, A3|en, 134, 1, E3|en, 164, 1, A4|en, 194, 1, C4|en, 224, 1, E4|en, 254, 1, A5|en, 28, 2, H5, E2|en, 58, 2, E3|en, 88, 2, Gis3|en, 118, 2, E4|en, 148, 2, Gis4|en, 178, 2, H5|en, 208, 2, C5, A3|en, 238, 2, E3|en, 12, 3, A4|en, 42, 3, E4|en, 72, 3, E5|en, 102, 3, Dis5|en, 132, 3, E5|en, 162, 3, Dis5|en, 192, 3, E5|en, 222, 3, H5|en, 252, 3, D5|en, 26, 4, C5|en, 56, 4, A5, A3|en, 86, 4, E3|en, 116, 4, A4|en, 146, 4, C4|en, 176, 4, E4|en, 206, 4, A5|en, 236, 4, H5, E2|en, 10, 5, E3|en, 40, 5, Gis3|en, 70, 5, E4|en, 100, 5, C5|en, 130, 5, H5|en, 160, 5, A5, A3|en, 190, 5, E3|en, 220, 5, A4|en, 24, 6, E5|en, 54, 6, Dis5|en, 84, 6, E5|en, 114, 6, Dis5|en, 144, 6, E5|en, 174, 6, H5|en, 204, 6, D5|en, 234, 6, C5|en, 8, 7, A5, A3|en, 38, 7, E3|en, 68, 7, A4|en, 98, 7, C4|en, 128, 7, E4|en, 158, 7, A5|en, 188, 7, H5, E2|en, 218, 7, E3|en, 248, 7, Gis3|en, 22, 8, E4|en, 52, 8, Gis4|en, 82, 8, H5|en, 112, 8, C5, A3|en, 142, 8, E3|en, 172, 8, A4|en, 202, 8, E4|en, 232, 8, E5|en, 6, 9, Dis5|en, 36, 9, E5|en, 66, 9, Dis5|en, 96, 9, E5|en, 126, 9, H5|en, 156, 9, D5|en, 186, 9, C5|en, 216, 9, A5, A3|en, 246, 9, E3|en, 20, 10, A4|en, 50, 10, C4|en, 80, 10, E4|en, 110, 10, A5|en, 140, 10, H5, E2|en, 170, 10, E3|en, 200, 10, Gis3|en, 230, 10, E4|en, 4, 11, C5|en, 34, 11, H5|en, 64, 11, A5, A3|en, 94, 11, E3|en, 124, 11, A4|en, 154, 11, H5|en, 184, 11, C5|en, 214, 11, D5|en, 244, 11, E5, C3|en, 18, 12, G3|en, 48, 12, C4|en, 78, 12, G4|en, 108, 12, F5|en, 138, 12, E5|en, 168, 12, D5, G2|en, 198, 12, G3|en, 228, 12, A4|en, 2, 13, F4|en, 32, 13, E5|en, 62, 13, D5|en, 92, 13, C5, A3|en, 122, 13, E3|en, 152, 13, A4|en, 182, 13, E4|en, 212, 13, D5|en, 242, 13, C5|en, 16, 14, H5, E2|en, 46, 14, E3|en, 76, 14, E4|en, 106, 14, E4|en, 136, 14, E5|en, 166, 14, E4|en, 196, 14, E5|en, 226, 14, E5|en, 0, 15, E6|en, 30, 15, Dis5|en, 60, 15, E5|en, 90, 15, Dis5|en, 120, 15, E5|en, 150, 15, Dis5|en, 180, 15, E5|en, 210, 15, Dis5|en, 240, 15, E5|en, 14, 16, Dis5|en, 44, 16, E5|en, 74, 16, Dis5|en, 104, 16, E5|en, 134, 16, H5|en, 164, 16, D5|en, 194, 16, C5|en, 224, 16, A5, A3|en, 254, 16, E3|en, 28, 17, A4|en, 58, 17, C4|en, 88, 17, E4|en, 118, 17, A5|en, 148, 17, H5, E2|en, 178, 17, E3|en, 208, 17, Gis3|en, 238, 17, E4|en, 12, 18, Gis4|en, 42, 18, H5|en, 72, 18, C5, A3|en, 102, 18, E3|en, 132, 18, A4|en, 162, 18, E4|en, 192, 18, E5|en, 222, 18, Dis5|en, 252, 18, E5|en, 26, 19, Dis5|en, 56, 19, E5|en, 86, 19, H5|en, 116, 19, D5|en, 146, 19, C5|en, 176, 19, A5, A3|en, 206, 19, E3|en, 236, 19, A4|en, 10, 20, C4|en, 40, 20, E4|en, 70, 20, A5|en, 100, 20, H5, E2|en, 130, 20, E3|en, 160, 20, Gis3|en, 190, 20, E4|en, 220, 20, C5|en, 250, 20, H5|en, 24, 21, A5, A3|en, 54, 21, E3|en, 84, 21, A4|en, 114, 21, H5|en, 144, 21, C5|en, 174, 21, D5|en, 204, 21, E5, C3|en, 234, 21, G3|en, 8, 22, C4|en, 38, 22, G4|en, 68, 22, F5|en, 98, 22, E5|en, 128, 22, D5, G2|en, 158, 22, G3|en, 188, 22, A4|en, 218, 22, F4|en, 248, 22, E5|en, 22, 23, D5|en, 52, 23, C5, A3|en, 82, 23, E3|en, 112, 23, A4|en, 142, 23, E4|en, 172, 23, D5|en, 202, 23, C5|en, 232, 23, H5, E2|en, 6, 24, E3|en, 36, 24, E4|en, 66, 24, E4|en, 96, 24, E5|en, 126, 24, E4|en, 156, 24, E5|en, 186, 24, E5|en, 216, 24, E6|en, 246, 24, Dis5|en, 20, 25, E5|en, 50, 25, Dis5|en, 80, 25, E5|en, 110, 25, Dis5|en, 140, 25, E5|en, 170, 25, Dis5|en, 200, 25, E5|en, 230, 25, Dis5|en, 4, 26, E5|en, 34, 26, Dis5|en, 64, 26, E5|en, 94, 26, H5|en, 124, 26, D5|en, 154, 26, C5|en, 184, 26, A5, A3|en, 214, 26, E3|en, 244, 26, A4|en, 18, 27, C4|en, 48, 27, E4|en, 78, 27, A5|en, 108, 27, H5, E2|en, 138, 27, E3|en, 168, 27, Gis3|en, 198, 27, E4|en, 228, 27, Gis4|en, 2, 28, H5|en, 32, 28, C5, A3|en, 62, 28, E3|en, 92, 28, A4|en, 122, 28, E4|en, 152, 28, E5|en, 182, 28, Dis5|en, 212, 28, E5|en, 242, 28, Dis5|en, 16, 29, E5|en, 46, 29, H5|en, 76, 29, D5|en, 106, 29, C5|en, 136, 29, A5, A3|en, 166, 29, E3|en, 196, 29, A4|en, 226, 29, C4|en, 0, 30, E4|en, 30, 30, A5|en, 60, 30, H5, E2|en, 90, 30, E3|en, 120, 30, Gis3|en, 150, 30, E4|en, 180, 30, C5|en, 210, 30, H5|en, 240, 30, A5, A3|en, 14, 31, E3|en, 44, 31, A4|en, 74, 31, C5, E4, C4, B4|en, 104, 31, C5, F4, C4, A4|en, 134, 31, C5, G4, E4, B4, G3|en, 164, 31, C5, F3|en, 194, 31, A4|en, 224, 31, C4|en, 254, 31, A4|en, 28, 32, F5, C4|en, 58, 32, A4|en, 73, 32, E5|en, 88, 32, E5, F3|en, 118, 32, B4|en, 148, 32, D4|en, 178, 32, B4|en, 208, 32, B6, D4|en, 238, 32, B4|en, 253, 32, A6|en, 12, 33, A6, F3|en, 42, 33, G5, E4|en, 72, 33, F5, B4, G3, F3|en, 102, 33, E5, E4|en, 132, 33, D5, B4, G3, F3|en, 162, 33, C5, E4|en, 192, 33, B5, F3|en, 222, 33, A4|en, 252, 33, A5, C4|en, 26, 34, A4|en, 56, 34, A5, C4|en, 71, 34, G4|en, 86, 34, A5, A4|en, 101, 34, B5|en, 116, 34, C5, F3|en, 146, 34, A4|en, 176, 34, C4|en, 206, 34, A4|en, 236, 34, D5, C4|en, 10, 35, Dis5, A4|en, 40, 35, E5, E3|en, 70, 35, A4|en, 100, 35, C4|en, 130, 35, E5, A4|en, 160, 35, F5, D4, D3|en, 190, 35, A5, F3|en, 220, 35, C5, G3|en, 250, 35, E4|en, 24, 36, G3|en, 54, 36, E4|en, 84, 36, D5, G3|en, 114, 36, G4|en, 129, 36, H5|en, 144, 36, D5, E4, C4|en, 159, 36, G5|en, 174, 36, G4|en, 189, 36, G5|en, 204, 36, A5|en, 219, 36, G5|en, 234, 36, H5, G4, F4|en, 249, 36, G5|en, 8, 37, C5, G4, E4|en, 23, 37, G5|en, 38, 37, D5, G4, F4, D4|en, 53, 37, G5|en, 68, 37, E5, G4, E4, C4|en, 83, 37, G5|en, 98, 37, C6|en, 113, 37, H6|en, 128, 37, A6, A4, F3|en, 143, 37, G5|en, 158, 37, F5|en, 173, 37, E5|en, 188, 37, D5, H4, G3|en, 203, 37, G5|en, 218, 37, F5|en, 233, 37, D5|en, 248, 37, D5, E4, C4|en, 7, 38, G5|en, 22, 38, G4|en, 37, 38, G5|en, 52, 38, A5|en, 67, 38, G5|en, 82, 38, H5, G4, F4|en, 97, 38, G5|en, 112, 38, C5, G4, E4|en, 127, 38, G5|en, 142, 38, D5, G4, F4, D4|en, 157, 38, G5|en, 172, 38, E5, G4, E4, C4|en, 187, 38, G5|en, 202, 38, C6|en, 217, 38, H6|en, 232, 38, A6, A4, F3|en, 247, 38, G5|en, 6, 39, F5|en, 21, 39, E5|en, 36, 39, D5, H4, G3|en, 51, 39, G5|en, 66, 39, F5|en, 81, 39, D5|en, 96, 39, E5, A4, Gis3|en, 111, 39, F5|en, 126, 39, E5|en, 141, 39, Dis5|en, 156, 39, E5|en, 171, 39, H5|en, 186, 39, E5|en, 201, 39, Dis5|en, 216, 39, E5|en, 231, 39, H5|en, 246, 39, E5|en, 5, 40, Dis5|en, 20, 40, E5|en, 110, 40, H5|en, 140, 40, E5|en, 170, 40, Dis5|en, 200, 40, E5|en, 48, 42, EoS|en][!--empirenews.page--] 单个音符播放和停止: def note_on( ser,key,chan ): realkey = (key&0x7F)+40 print("key on: %u "% realkey ) midiNoteOn(ser,chan, realkey, 127); def note_off( ser,key,chan ): realkey = (key&0x7F)+40 print("key off: %u "% realkey ) midiNoteOff(ser,chan, realkey, 127); def note_all_off( ser ): print("key off" ) midiNoteAllOff(ser,0) 播放乐谱的函数 def play_tone( ser,tone ): name = input("Push Enter to play!") print("Song Start") score_idx = 0 s = 0 sleeptime0 = 0 sleeptime1 = 0 sleeptime = 0 tickcount = 0 chan = 0 while score_idx < len(tone): sleeptime0 = (tone[score_idx]+tone[score_idx+1]*256)*8/1000 sleeptime = sleeptime0-sleeptime1 sleeptime1 = sleeptime0 print("sleep: %5.2f"%sleeptime) time.sleep(sleeptime) note_all_off(ser) score_idx = score_idx+2 always = 1 while always == 1: s = tone[score_idx] score_idx = score_idx+1 if s== EoS: print("Song End") return else: note_on(ser,s,chan) if (s&en)!=0: if tickcount<7: tickcount=tickcount+1; else: tickcount = 0 if chan==0: chan=1 else: chan = 0 break; 测试程序 ser = vs1053_midi.vs1053_midi_setup("com5") #vs1053_midi.test_play_loop(ser,5) vs1053_midi.play_tone(ser,vs1053_midi.tone) 程序运行如下:

    时间:2018-08-09 关键词: MP3 解码 音频 播放器 嵌入式音频 audio adafruit feather ogg

  • 51单片机红外控制解码详解

    红外遥控发射芯片采用PPM编码方式,当发射器按键按下后,将发射一组108ms的编码脉冲。遥控编码脉冲由前导码、8位用户码、8位用户码的反码、8位操作码以及8位操作码的反码组成。通过对用户码的检验,每个遥控器只能控制一个设备动作,这样可以有效地防止多个设备之间的干扰。编码后面还要有编码的反码,用来检验编码接收的正确性,防止误操作,增强系统的可靠性。前导码是一个遥控码的起始部分,由一个9ms的低电平(起始码)和一个4. 5ms的高电平(结果码)组成,作为接受数据的准备脉冲。以脉宽为0. 56ms、周期为1. 12ms的组合表示二进制的“0”;以脉宽为1. 68ms、周期为2. 24ms的组合表示二进制的“1”。如果按键按下超过108ms仍未松开,接下来发射的代码(连发代码)将仅由起始码(9ms)和结束码(2. 5ms)组成。单片机采用外部中断INTI管脚和红外接收头的信号线相连,中断方式为边沿触发方式。并用定时器0计算中断的间隔时间,来区分前导码、二进制的“1”、“0”码。并将8位操作码提取出来在数码管上显示。// 解码值在Im[2]中,当IrOK=1时解码有效。/* 51单片机红外遥控解码程序 *///用遥控器对准红外接收头,按下遥控器按键,在数码管前两位上就会显示对应按键的编码#include #define uchar unsigned charsbit dula=P2^6;sbit wela=P2^7;uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d, 0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};uchar f;#define Imax 14000 //此处为晶振为11.0592时的取值,#define Imin 8000 //如用其它频率的晶振时,#define Inum1 1450 //要改变相应的取值。#define Inum2 700#define Inum3 3000unsigned char Im[4]={0x00,0x00,0x00,0x00};uchar show[2]={0,0};unsigned long m,Tc;unsigned char IrOK;void delay(uchar i){ uchar j,k;for(j=i;j>0;j--) for(k=125;k>0;k--);}void display(){ dula=0; P0=table[show[0]]; dula=1; dula=0; wela=0; P0=0xfe; wela=1; wela=0; delay(5); P0=table[show[1]]; dula=1; dula=0; P0=0xfd; wela=1; wela=0; delay(5);}//外部中断解码程序void intersvr1(void) interrupt 2 using 1{Tc=TH0*256+TL0; //提取中断时间间隔时长TH0=0; TL0=0; //定时中断重新置零if((Tc>Imin)&&(TcInum1&&Tc>1|0x80; m++; } if(Tc>Inum2&&Tc>1; m++; //取码}if(m==32) { m=0; f=0; if(Im[2]==~Im[3]) { IrOK=1; } else IrOK=0; //取码完成后判断读码是否正确 } //准备读下一码 }}/*演示主程序*/void main(void){ unsigned int a;m=0; f=0;EA=1;IT1=1;EX1=1;TMOD=0x11;TH0=0;TL0=0;TR0=1;//ET0=1;while(1){ if(IrOK==1){ show[1]=Im[2] & 0x0F; //取键码的低四位 show[0]=Im[2] >> 4; IrOK=0;} for(a=100;a>0;a--) { display();}}}

    时间:2018-07-31 关键词: 解码 51单片机 红外控制

  • 基于stm32f103zet6之红外遥控解码的学习

    一、红外遥控解码部分从昨天开始整,一直到现在才解码成功!中途遇到了不少问题,结果出来后还是觉得有必要总结一下,唉!1、首先我又是怀疑我硬件电平不兼容德问题,后来给接上3.3V的电压,还是不行,好吧,算失败了,在网上查阅了比较多的帖子,也找了比较多的资料,最终还是决定用原本那个生了锈的遥控来解码!2、然后准备参照着原来51的思想来移植代码,也确实找到类似的代码貌似使用的2.0的库写的,单步调试了半天,总感觉在延时部分出了点问题,所以比较郁闷,好吧,分析来分析去的,结果真的是没有半点现象啊!果断网上求助,游荡了一会,压根没人理,高手不屑一顾呀!!偶然间让我遇到了原子哥的那段红外的代码,拖出来分析,所以就有了今晚解码成功的结果!3、我照着原子的移植,我用的是自己的延时,也就是系统定时器,MTD,单步调试的时候,发现居然死在了systick那里,进不了中断,一步步观察,好像导致进不了中断的原因就是:我已经进了外部中断,心想,没道理啊,系统定时器的优先级不应该是高于外部中断的么,因为他是核决定的呀(至少我是这么想的),然后又查了相关资料,据说系统定时器的中断优先级是最低的,这时候我才恍然大悟!现在开始分析代码,虽然说原子的代码风格不怎么样,但是个人觉得他真的好牛逼,库函数是人家ST公司搞出来的,我想,原子的这套代码,应该基本上是他自己一个人整出来的吧!二、所谓红外遥控!(针对我手上的红外遥控)1、红外解码一直是单片机中应用较多的,需要设备加装专用解码芯片,这就大大减轻了单片机的负担。需要单片机样例使用延时做红外解码,比较容易理解,下面通过TC9012和uPD6121芯片为例大致了解解码原理:先看一接收头产生的波形图,这是原子的一张图 % U, K" ?3 K2 _( j' a! e: K: o从上图可以看出 9.0ms高电平+4.5ms低电平称为头码,用于识别是否遥控码开始,这是一张连续发射码的波形图(就是一直按下某一遥控器按键)。; n5 [+ z; ^4 d( T# L) h" Y6 B5 j3 T头码过后会出现4个8位的数据,我们最终目的就是要把这个 32位(4x8)从一体化红外接收头提取出来,并转换成16进制数,用于区分不同按键按下得出的不同数值。在遥控器发射波形中,可以知道,8位数中的0或者1不是用高低电平表示,而是用不同的低电平的宽度表示,0.565ms表示0,1.69ms表示1,2个位中间还会有一个0.56ms的高电平 看到如上图波形,表示单片机引脚可以接收到的波形,我们只要通过单片机读取波形并分析波形的宽度,然后分辨出是头码,还是0或者1,最后整理出这组码的16进制组合。正确的解码结果是按同一个按键得出的16进制数值是不变化的。通过这个原理,我们可以分辨出每个按键的键值。! z7 B/ `2 Q: z基本原理分析如下,如接收到头码是4.5ms低电平+4.5ms高电平,我们分析 第一个下降沿到第二个下降沿的宽度是 9ms,我们判断这个头码可以给定一个范围,只要数据在这个范围内则认为头码是正确的,检测头码正确后接着检测剩下的32位数值。2、用自己的话概括就是:平常是高电平--->按键按下--->产生引导码(9+4.5)ms--->然后判断是不是连续发送--->1还是0--->存储码值--->转换码值!简单就是这样!3、首先是我的主程序,代码注释都非常详细,不解释了!注意码值需要依据自己的遥控而定,我就是单步测试出来的!#include"stm32f10x.h"#include"Usart.h"#include"stdio.h"#include"Remote_Control.h"#include"Delay.h"/**************************PA1接红外接收端************************************//************由于没有做外设测试的程序是:按键PA0仅一个LED灯*******************//*******由于没有做外设测试的程序是:串口采用的是PA9->(TT),PA9->(RR)*****/intmain(void){u8key;USART1_Config();delay_init(72);//延时初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置NVIC中断分组2:2位抢占优先级,2位响应优先级printf("rn("__DATE__"-"__TIME__")rn");Remote_Init();while(1){if(Remote_Rdy){key=Remote_Process();switch(key){case0x68:printf("0n");break;//0case0x30:printf("1n");break;//1case0x18:printf("2n");break;//2case0x7a:printf("3n");break;//3case0x10:printf("4n");break;//4case0x38:printf("5n");break;//5case0x5a:printf("6n");break;//6case0x42:printf("7n");break;//7case0x4a:printf("8n");break;//8case0x52:printf("9n");break;//9default:break;}}}}4、然后是驱动程序/*-------------------------协议--------------------------开始拉低9ms,接着是一个4.5ms的高脉冲,通知器件开始传送数据了接着是发送4个8位二进制码,第一二个是遥控识别码(REMOTE_ID),第一个为正码(0),第二个为反码(255),接着两个数据是键值,第一个为正码第二个为反码.发送完后40ms,遥控再发送一个9ms低,2ms高的脉冲,表示按键的次数,出现一次则证明只按下了一次,如果出现多次,则可以认为是持续按下该键.---------------------------------------------------------*/#include"Remote_Control.h"#include"Delay.h"u32Remote_Odr=0;//命令暂存处u8Remote_Cnt=0;//按键次数,此次按下键的次数u8Remote_Rdy=0;//红外接收到数据/************************初始化红外接收引脚的设置**********************************//******************选择PA1脚作为外部中断,用于红外输入*****************************/voidRemote_Init(void){GPIO_InitTypeDefGPIO_InitStructure;//GPIONVIC_InitTypeDefNVIC_InitStructure;//中断EXTI_InitTypeDefEXTI_InitStructure;//外部中断线RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; //注

    时间:2018-07-27 关键词: 解码 红外遥控 stm32f103zet6

  • ARM指令寻址方式之: 数据处理指令的寻址方式

    ARM指令寻址方式之: 数据处理指令的寻址方式

    4.1 数据处理指令的寻址方式4.1.1 数据处理指令的寻址方式概要数据处理指令的基本语法格式如下。<opcode> {<cond>} {S} <Rd>,<Rn>,<shifter_operand>其中<shifter_operand>有下面11种形式,如表4.1所示。表4.1 <shifter_operand>的寻址方式语 法寻 址 方 式1#<immediate>立即数寻址2<Rm>寄存器寻址3<Rm>, LSL #<shift_imm>立即数逻辑左移4<Rm>, LSL <Rs>寄存器逻辑左移5<Rm>, LSR #<shift_imm>立即数逻辑右移6<Rm>, LSR <Rs>寄存器逻辑右移7<Rm>, ASR #<shift_imm>立即数算术右移8<Rm>, ASR <Rs>寄存器算术右移9<Rm>, ROR #<shift_imm>立即数循环右移10<Rm>, ROR <Rs>寄存器循环右移11<Rm>, RRX寄存器扩展循环右移数据处理指令的寻址方式根据<shifter_operand>的不同,相应的分为11种。4.1.2 指令解码图4.1显示了数据处理指令不同寻址方式下的解码格式。图4.1 数据操作指令编码格式编码格式中各域含义如下。· <opcode>:确定具体指令。· S:标识指令是否影响程序状态寄存器CPSR条件标志。· Rd:指令操作的目的寄存器。· Rn:指令第一源操作数。· bit[11∶0]:移位操作,详见本章移位操作一节。· bit[25]:被用来区分是立即数移位操作还是寄存器移位操作。如果指令编码出现下面情况:bit[25] = 0并且bit[4] = 1并且bit[7] = 1,则指令并非数据处理指令,它可能是Load/Store指令或算术指令。4.1.3 移位操作数据处理指令是在算术逻辑单元ALU中完成。ARM处理器一个显著特征就是可以在操作数进入ALU之前,对操作数进行指定位数的左移或右移操作。这种功能明显增强了数据处理操作的灵活性。移位操作可能产生进位,更新程序状态寄存器CPSR的进位标志C。移位操作有下面3种基本方式。1.立即数方式没有任何一条ARM指令可以包含一个32位的立即数,数据处理指令编码格式中,第二个操作数有12位。指令的编码格式如图4.1所示。指令中的立即数是由一个8 bit的常数移动4 bit偶数位(0,2,4,…,26,28,30)得到的。所以,每一条指令都包含一个8 bit的常数X和移位值Y,得到的立即数=X循环右移(2×Y)。注意8位立即数一定要移偶数位。下面列举了一些有效的立即数。0xFF、0x104、0xFF0、0x FF00、0x FF000、0x FF000000、0x F000000F下面是一些无效的立即数。0x101、0x102、0x FF1、0x FF04、0x FF003、0x FFFFFFFF、0x F000001F下面是一些应用立即数的指令。MOV r0,#0 ;送0到r0ADD r3,r3,#1 ;r3的值加1CMP r7,#1000 ;r7的值和1000比较BIC r9,r8,#0x FF00 ;将r8中8~15位清零,结果保存在r9中2.寄存器方式寄存器的值可以被直接用于数据操作指令,如:MOV r2,r0 ;r0的值送r2ADD r4,r3,r2 ;r2加r3,结果送r4CMP r7,r8 ;比较r7和r8的值3.寄存器移位方式寄存器的值在被送到ALU之前,可以事先经过桶形移位寄存器的处理。预处理和移位发生在同一周期内,所以有效的使用移位寄存器,可以增加代码的执行效率。具体的移位(或者循环移位)方式有下面几种。· ASR:算术右移。· LSL:逻辑左移。· LSR:逻辑右移。· ROR:循环右移。· RRX:扩展的循环右移。以上5种移位方式,移位值均可以由立即数或寄存器指定。下面是一些在指令中使用了移位操作的例子。ADD r2,r0,r1,LSR #5MOV r1,r0,LSL #2RSB r9,r5,r5,LSL #1SUB r1,r2,r0,LSR #4MOV r2,r4,ROR r04.1.4 寻址方式分类详解数据处理指令的寻址方式根据<shifter_operand>的不同,相应的分为11种。详见表4.1。下面对各类寻址方式进行详细说明。1.#<immediate>(1)编码格式指令的编码格式如图4.2所示。图4.2 数据处理指令——立即数寻址编码格式立即数寻址为数据处理指令提供了一个可直接操作的立即数。立即数的生成方法见前面章节介绍。如果移位值为0,则移位进位值为程序状态寄存器CPSR的C标志位;否则,为32-bit立即数的bit[31]。(2)操作伪代码Shifter_operand = immed_8 Rotate_Right (rotate_imm*2)if rotate_imm == 0 then shifter_carry_out = C flagelse /* rotate_imm != 0*/ shifter_carry_out = shifter_operand[31](3)说明① 并不是所有的32-bit立即数都是可以使用的合法立即数。只有那些通过将一个8-bit的立即数循环右移偶数位可以得到的立即数才可以在指令中使用。② 有些立即数可以通过不止一种方法得到。由于立即数的构造方法中移位包含了循环操作,而循环移位操作会影响CPSR的条件标志位C。因此,同一个合法的立即数由于采用了不同的编码方式,将使这些指令的执行产生不同的结果,这是不能允许的。ARM汇编器按照下面的规则来生成立即数的编码。· 当立即数数值在0和0xFF范围时,令immed_8=<immediate>,immed_4=0。· 其他情况下,汇编编译器选择使用immed_4数值最小的编码方式。③ 为了更精确地控制立即数的生成,可以使用下面的语法格式控制立即数的生成。#<immed_8>,<rotate_amout>其中,<rotate_amout> = 2*rotate_imm(4)举例SUBS r0,r0,#1 ;寄存器r0中的数值减1,结果保存到r0MOV r0,#0xff00 ; 0xff00 → r0 ;将立即数0xff00放入r0保存2.<Rm>(1)编码格式指令的编码格式如图4.3所示。图4.3 数据处理指令——寄存器寻址编码格式指令的操作数即为寄存器中的数值。移位寄存器的进位为程序状态寄存器CPSR的C标志位。指令的语法格式为:<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>(2)操作伪代码Shifter_operand = RmShifter_carry_out = C Flag(3)说明① 从指令的解码格式来看,寄存器寻址方式和使用立即数逻辑左移寻址解码格式是相同的,只是其移位数为0。② 如果指令中的Rm或Rn指定为程序计数器r15,则操作数的值为当前指令地址加8。(4)举例MOV r1,r2 ; r2 → r1SUB r0,r1,r2 ; r1 – r2 → r03.<Rm>, LSL #<shift_imm>(1)编码格式指令的编码格式如图4.4所示。图4.4 数据处理指令——立即数逻辑左移寻址编码格式指令的操作数为寄存器Rm的数值逻辑左移shift_imm位。左移的范围在0到31之间。左移移出的位用0补齐。进位标志位是最后移出的位(如果移位数为0,则为C标志位)。指令的语法格式为:<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,LSL #<shift_imm>,其中:· <Rm>为进行逻辑左移操作的寄存器;· LSL为逻辑左移操作标识;· <shift_imm>为逻辑左移位数,范围为0~31。(2)操作伪代码if shift_imm == 0 then /*执行寄存器操作*/ shifter_operand = Rm shifter_carry_out = C flagelse /*移位寄存器大于零*/ shifter_operand = Rm logical_shift_left shift_imm shifter_carry_out = Rm[32 – shift_imm](3)说明① 如果移位立即数<shift_imm> =0,则该寻址方式为立即数直接寻址。② 如果指令中的Rm或Rn指定为程序计数器r15,则操作数的值为当前指令地址加8。(4)举例SUB r0,r1,r2,LSL #10 ;r1的值减去r2的值左移10bit,结果放到r0寄存器MOV r0,r2,LSL #3 ;r2的值左移3bit,结果放入r0,即r0 = r2×84.<Rm>, LSL <Rs>(1)编码格式指令的编码格式如图4.5所示。图4.5 数据处理指令——寄存器逻辑左移寻址编码格式寄存器逻辑左移十分适合寄存器值乘2的倍数操作。这个指令是将寄存器Rm的值逻辑左移一定的位数。位移的位数由Rs的最低8位bit[7∶0]决定。Rm移出的位用0补齐。进位值是移位寄存器最后移出的位,如果移位数大于0,则进位值为0。(2)语法格式<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,LSL <Rs>其中:· <Rm>为指令被移位的寄存器;· LSL为逻辑左移操作标识;· <Rs>为包含逻辑左移位数的寄存器。(3)操作伪代码if Rs[7:0] = = 0 then shifter_operand = Rm shifter_carry_out = C flagelse if Rs[7:0] < 32 then shifter_operand = Rm logical_shift_left Rs[7:0] shifter_carry_out = Rm[32 – Rs[7:0]]else if Rs[7:0] = = 32 then shifter_operand = 0 shifter_carry_out = Rm[0]else /*Rs的后8位大于零*/ shifter_operand = 0 shifter_carry_out = 0(4)说明如果程序计数器r15被用作Rd,Rm,Rn或Rs中的任意一个,则指令的执行结果不可预知。(5)举例MOV r0,r2,LSL r3 ;r2的值左移r3位,结果放入r0ANDS r1,r1,r2,LSL r3 ;r2的值左移r3位,然后和r1相与,结果放入r15.<Rm>, LSR #<shift_imm>(1)编码格式指令的编码格式如图4.6所示。图4.6 数据处理指令——立即数逻辑右移寻址编码格式指令的操作数为寄存器Rm的值右移<shift_imm>位,相当于Rm的值除以一个2的倍数。<shift_imm>值的范围为0~31,移位后空出的位添0。循环器进位值为Rm最后移出的位。(2)语法格式<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,LSR #<shift_imm>其中:· <Rm>为被移位的寄存器;· LSR为逻辑右移操作标识;· <shift_imm>为逻辑右移位数,范围为0~31。(3)操作伪代码if shift_imm == 0 then /*执行寄存器操作*/ shifter_operand = 0 shifter_carry_out = Rm[31]else /*移位立即数大于零*/ shifter_operand = Rm logical_shift_Right shift_imm shifter_carry_out = Rm[shift_imm - 1](4)说明① shift_imm的取值范围为0~31,当shift_imm=0时,移位位数为32,所以移位位数范围为1~32位。② 如果指令中的Rm或Rn指定为程序计数器r15,则操作数的值为当前指令地址加8。6.<Rm>, LSR <Rs>(1)编码格式指令的编码格式如图4.7所示。图4.7 数据处理指令——寄存器逻辑右移寻址编码格式此操作将寄存器Rm的数值逻辑右移一定的位数。移位的位数由Rs的最低8位bit[7∶0]决定。移出的位由0补齐。当Rs[7∶0]大于0而小于32时,进位标志C由最后移出的位决定,当Rs[7∶0]大于32时,进位标志位为0,当Rs[7∶0]等于0时,进位标志不变。(2)语法格式<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,LSR <Rs>其中:· <Rm>为指令被移位的寄存器;· LSR为逻辑右移操作标识;· <Rs>为包含逻辑右移位数的寄存器。(3)操作伪代码if Rs[7:0] = = 0 then shifter_operand = Rm shifter_carry_out = C flagelse if Rs[7:0] < 32 then shifter_operand = Rm logical_shift_Right Rs[7:0] shifter_carry_out = Rm[Rs[7:0] - 1]else if Rs[7:0] = = 32 then shifter_operand = 0 shifter_carry_out = Rm[31]else /*Rs的后8位大于零*/ shifter_operand = 0 shifter_carry_out = 0(4)说明如果程序计数器r15被用作Rd、Rm、Rn或Rs中的任意一个,则指令的执行结果不可预知。7.<Rm>, ASR #<shift_imm>(1)编码格式指令的编码格式如图4.8所示。图4.8 数据处理指令——立即数算术右移寻址编码格式指令的操作数为寄存器Rm的数值逻辑右移<shift_imm>位。<shift_imm>的值范围为0~31,当<shift_imm>等于0时,移位位数为32,所以移位位数范围为1~32位。进位移位操作后,空出的位添Rm的最高位Rm[31]。进位标志为Rm最后被移出的数值。(2)语法格式<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,ASR #<shift_imm>其中:· <Rm>为被移位的寄存器;· ASR为算术右移操作标识;· <shift_imm>为算术右移位数,范围为1~32,当shift_imm等于0时移位位数为32。(3)操作伪代码if shift_imm == 0 then /*执行寄存器操作*/ if Rm[31] = = 0 then shifter_operand = 0 shifter_carry_out = Rm[31] else /*Rm[31] = = 1*/ shifter_operand = 0xffffffff shifter_carry_out = Rm[31]else /*shift_imm > 0*/ shifter_operand = Rm Arithmetic_shift_Right <shift_imm> shifter_carry_out = Rm[shift_imm - 1](4)说明① 如果指令中的Rm或Rn指定为程序计数器r15,则操作数的值为当前指令地址加8。8.<Rm>, ASR <Rs>(1)编码格式指令的编码格式如图4.9所示。图4.9 数据处理指令——寄存器算术右移寻址编码格式此操作将寄存器Rm的数值算术右移一定的位数。移位后空缺的位由Rm的符号位(Rm[31])填充。位移的位数由Rs的最低8位bit[7∶0]决定。当Rs[7∶0]大于零而小于32时,指令的操作数为寄存器Rm的数值算术右移Rs[7∶0]位,进位标志C为Rm最后被移出的位。(2)语法格式<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,ASR <Rs>其中:· <Rm>为指令被移位的寄存器;· ASR为算术右移操作标识;· <Rs>为包含算术右移位数的寄存器。(3)操作伪代码if Rs[7:0] = = 0 then shifter_operand = Rm shifter_carry_out = C flagelse if Rs[7:0] < 32 then shifter_operand = Rm Arithmeticl_shift_Right Rs[7:0] shifter_carry_out = Rm[Rs[7:0] - 1]else if Rm[31] = =0 then shifter_operand = 0 shifter_carry_out = Rm[31] else shifter_operand = 0xffffffff shifter_carry_out = Rm[31](4)说明如果程序计数器r15被用作Rd、Rm、Rn或Rs中的任意一个,则指令的执行结果不可预知。9.<Rm>, ROR #<shift_imm>(1)编码格式指令的编码格式如图4.10所示。图4.10 数据处理指令——立即数循环右移寻址编码格式指令的操作数由寄存器Rm的数值循环右移一定的位数得到。移位的位数由Rs的最低8位bits[7∶0]决定。当Rs[7∶0]=0时,指令的操作数为寄存器Rm的值,循环器的进位值为CPSR中的C条件标志位;否则,循环器的进位值为Rm最后被移出的位。(2)语法格式<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,ROR #<shift_imm>其中:· <Rm>为被移位的寄存器;· ROR为循环右移操作标识;· <shift_imm>为循环右移位数,范围为1~31,当shift_imm等于0时执行RRX操作。(3)操作伪代码if shift_imm == 0 then /*执行寄存器操作*/ 执行RRX操作else shifter_operand = Rm Rotate_Right shift_imm shifter_carry_out = Rm[shift_imm - 1](4)说明如果指令中的Rm或Rn指定为程序计数器r15,则操作数的值为当前指令地址加8。10.<Rm>, ROR <Rs>(1)编码格式指令的编码格式如图4.11所示。图4.11 数据处理指令——寄存器循环右移寻址编码格式指令的操作数由寄存器Rm的数值循环右移一定的位数。移位的位数由Rs的最低8位bits[7∶0]决定。当Rs[7∶0]=0时,指令的操作数为寄存器Rm的值,循环器的进位值为CPSR中的C条件标志位;否则,循环器的进位值为Rm最后被移出的位。(2)语法格式<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,ROR <Rs>其中:· <Rm>为指令被移位的寄存器;· ROR为循环右移操作标识;· <Rs>为包含循环右移位数的寄存器。(3)操作伪代码if Rs[7:0] = = 0 then shifter_operand = Rm shifter_carry_out = C flagelse if Rs[4:0] == 0 then shifter_operand = Rm shifter_carry_out = Rm[31]else shifter_operand = Rm Rotate_Right Rs[4:0] shifter_carry_out = Rm[Rs[4:0] - 1](4)说明如果程序计数器r15被用作Rd、Rm、Rn或Rs中的任意一个,则指令的执行结果不可预知。11.<Rm>, RRX(1)编码格式指令的编码格式如图4.12所示。图4.12 数据处理指令——扩展右移寻址编码格式指令的操作数为寄存器Rm的数值右移一位,并用CPSR中的C条件标志位填补空出的位。CPSR中的C条件标志位则用移出的位代替。(2)语法格式<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,RRX其中:· <Rm>为指令被移位的寄存器;· RRX为扩展的循环右移操作。(3)操作伪代码shifter_operand = (C flag logical_shift_left 31) OR (Rm logical_shift_Right 1)shifter_carry_out = Rm[0](4)说明① 此种寻址方式的编码形式和“ROR #0”一致。② 如果程序计数器r15被用作Rd、Rm、Rn或Rs中的任意一个,则指令的执行结果不可预知。③ 可以实现ADC指令的功能。

    时间:2018-06-14 关键词: ARM 解码 基础教程 数据处理指令 指令寻址

  • 示波器DALI协议触发与解码

    对于广泛应用在灯光照明控制系统中的DALI协议,ZDS2022示波器为您提供了完全开放的触发与解码模块,今天来共享下在ZDS2022示波器中,如何对DALI协议进行触发与解码操作?  按下【Decode】键,将解码类型设为DALI协议,开启协议触发,在示波器前面板上的触发控制区内按下【Auto/Normal】键,将触发方式由自动设为普通,按下协议参数软键,可对总线和触发模式相关内容进行设置,由于DALI协议的传输方式主要分为两种:Forward和Backward。  图1 DALI协议触发与解码  ZDS2022示波器DALI协议触发模式包括4种类型:开始位触发(BEGIN)、包含19个 bit的Forward消息帧触发,包含27 个bit的Forward消息帧触发和Backward触发。我们旋转旋钮A将触发模式设为Forward27触发,然后设置地址位、命令1和命令2的具体值,将地址位设为0xFF,命令1设为0xFF,命令2设为0xFF。屏幕上协议已经稳定触发,按下【Horiz】键,将储存深度设为112Mpts,保证波形放大时检测到完整帧,有效解码,放大波形细节观察解码事件,同时,可打开事件表,旋转旋钮B浏览DALI所有解码事件。

    时间:2018-06-08 关键词: 解码 触发 示波器 dali协议

  • 示波器CAN协议解码

      摘要:  CAN协议广泛应用于汽车电子行业,ZDS2022示波器也标配了CAN协议解码的功能,如果您对CAN的解码操作可能不太熟悉,本期视频将彻底解决您的疑惑!  正文:  CAN协议广泛应用于汽车电子行业,ZDS2022示波器拥有21种协议解码功能,CAN当然位列其中!  图1 选择CAN协议解码  如果您对CAN的解码操作可能不太熟悉,本期视频将彻底解决您的疑惑!  以演示板上的CAN信号为例,接入信号后,首先我们调整时基,使CAN信号以最佳视觉波形显示在屏幕上。按下【Decode】键进行解码,设置解码类型为CAN,打开协议触发,此时若波形并无稳定有效解码,按下“解码设置”,将自动阈值设置成手动阈值,调整每个通道的阈值,这时,我们看到协议已经有效解码,但是还没有稳定,因为此时触发方式是自动,将其设置为普通触发,即可稳定显示,此时打开事件表,对屏幕上解码的协议事件一目了然!图2 CAN协议解码之后打开事件表ZDS2022示波器21种常用协议解码,完全开放,非常实用,机会不容错过哦!

    时间:2018-06-08 关键词: 解码 示波器 can协议

  • 示波器HDQ协议解码

      大家好,在智能电池的检测模块中会用到HDQ协议,以便监测采集电池的电量、温度、电压和充电状态等信息。ZDS2022示波器对HDQ协议提供了免费的解码分析模块供用户使用,该如何操作呢?  按下【Decode】键,将解码类型设为HDQ协议,开启协议触发,按下协议参数软键,可对总线和触发参数进行设置,信源通道根据实际输入信号通道可设置为通道1,数据长度包括8位和16位,选择16位。  图1 HDQ协议解码  触发模式包括复位段和指令两种类型,可选择复位段,屏幕上协议波形已有效解码,打开事件表,可看到全部解码事件,旋转旋钮B可查看所有解码事件,在停止状态下,可短按旋钮B可将选中的解码事件准确定位在屏幕中央。

    时间:2018-06-08 关键词: 解码 示波器 hdq协议

  • 示波器FlexRay协议解码

    对于汽车行业中常用的高速、具备故障容错能力的FlexRay总线,您还在单独购买模块去解析吗?ZDS2022示波器为您免费开放的21种协议触发与解码中就已包括了FlexRay总线!今天和大家分享FlexRay总线的解码操作!  按下【Decode】键,将解码类型设为FlexRay,开启协议触发,在前面板上的触发控制区内按下【Auto/Normal】键,将触发方式由自动设置为普通触发方式,按下协议参数软键,对总线和触发进行相关设置,信源选择设置为通道1,ZDS2022示波器为FlexRay总线提供了3种通信频率,其中包括2.5Mbps、5Mbps和10Mbps,短按旋钮A,我们选择10Mbps。触发模式包括传输起始序列TSS和Frame ID(帧ID)两种,当您将触发模式设置为Frame ID时,需指明在系统设计过程中分配到每个节点的ID值,还要进一步设置负载帧标志、空帧标志、同步帧标志和起始帧标志,我们选择TSS触发模式。  图1 FlexRay协议解码  保证有效解码的前提不仅要设置正确的协议参数,还应该设置合适的阈值,按下解码设置软键,将自动阈值设为手动阈值,旋转旋钮A设置合理的通道阈值,旋钮A为微调,旋钮B为粗调,最终打开事件表,通过旋转旋钮B可对所有解码事件进行查看,在停止状态下,可短按旋钮B,则解码事件会准确定位在屏幕中央。

    时间:2018-06-08 关键词: 解码 示波器 flexray协议

  • 示波器PS/2协议解码

      大家好,我们日常生活中使用的PS/2接口的键盘和鼠标所遵循的协议即所谓的PS/2协议,ZDS2022示波器免费为您提供了PS/2协议的触发与解码,您知道如何进行解码操作吗?  按下【Decode】键,将解码类型设为PS/2,打开协议触发,按下协议软键,可看到总线设置和触发设置,设置时钟信源为通道1,数据信源设为通道2,由于之前开启了协议触发,故在这里可对触发进行相关设置,触发模式包括起始位和数据两种,我们设置起始位触发,数据传输方向可发向主机,也可发向从机,我们设为发向主机。  图1 PS/2协议解码  返回到主界面,PS/2协议已经有效解码,打开事件表,旋转旋钮B可对所有解码事件进行查看,在停止状态下,ZDS2022示波器还支持对协议 解码 分析事件表导出功能!

    时间:2018-06-08 关键词: 解码 示波器 ps 2协议

  • 示波器QC2.03.0快充协议解码

    示波器QC2.03.0快充协议解码

    QC2.0/3.0是高通在近年主推的手机快速充电协议,得益于芯片在手机领域的市场占有率,QC3.0快速充电已经广泛用于小米、中兴等主流机型。这里将和大家共同探讨QC2.0/3.0快充协议解码。 一、简介 QC2.0/3.0是高通在近两年制定的手机快充协议,相比联发科和OPPO的快充协议,高通QC快速充电技术在智能手机领域的占有率最高。QC2.0现在趋于普及,针对智能手机定制的ClassA标准支持5V、9V和12V输入电压。QC3.0则在QC2.0的基础上,支持200mv步进的渐变调节电压。目前已在ZDS4000全系列示波器中免费支持,用户可到广州致远电子网官下载最新固件免费升级。 二、协议说明 1、协议流程   图1 协议流程 2、电压状态 QC快充协议使用USB接口的D+和D-引脚,通过三态电压的变化来描述不同的状态。三种状态分别是3.3V、0.6V和GND。电压状态表图2所示:   图2 电压状态 三、解码实例 由于该QC快充协议中需要区分0.6V和GND,因此在解码时,通道的垂直档位需要设置到合适的位置,建议是1V/div或者500mv/div。同时,由于该协议的波形一般持续时间较长,因此建议使用ROLL 模式先抓取足够长的波形,然后在STOP下进行解码分析。 建议解码步骤: 1) 设置好每个通道的垂直档位和偏移,尽可能地占满屏幕区域; 2) 调节水平档位进入ROLL模式,抓取一定时间长度的信号波形;   图3 长时间的解码结果   图4 步进调值的解码   图5 复位信号的解码 针对智能手机快速充电协议,ZDS4000系列示波器可直接解码USB-PD、QC2.0/3.0。

    时间:2017-10-09 关键词: 解码 嵌入式开发 示波器 快充协议 qc2.03.0

  • 基于FPGA的IRIG-B码解码器设计

    摘要 针对基于单片机的IRIG—B码解码器解码精度低、工作稳定性差等问题,提出了一种基于FPGA的IRIG—B码解码器设计。在实现过程中着重分析了输入 IRIG—B码信号的毛刺问题,并采用三级D触发器后接或门的方法,彻底消除毛刺对本系统稳定性的影响。通过仿真验证了本系统具有解码精度高、工作稳定性强、易于实现等优点。 关键词 IRIG—B码;解码;毛刺 美国靶场司令委员会(Range Commanders Council,RCC)下属机构靶场间仪器组(Inter—Range Instrumen—tation Croup,IRIG)为保证靶场试验中各参试设备协同工作,制定了一种时间标准IRIG—B码(简称B码),由靶场时统站发送该码,各设备接收此信号后再结合其测量数据,从而达到测量数据的时间同步。我国靶场测量、控制、计算、通信、气象等测试设备,均采用IRIG—B码作为时间同步标准,其特点是可靠性高、接口标准、通用规范及使用灵活方便。 1 B码简介 IRIG—B码为一种串行的时间格式,其中每个脉冲称为码元。IRIG—B码的帧速率为1 fip·s-1,一帧数据由100个码元组成,分为第0、1、2、…、99个码元,每个码元长度为10 ms。时间格式中秒、分、时均用BcD码表示,低位在前,高位在后。第1、2、3、4、6、7、8码元属于“秒”信息,共占用7个码元;第10、11、 12、13、15、16、17码元属于“分”信息,共占用7个码元;第20、21、22、23、25、26码元属于“时”信息,共占用6个码元;第30、 31、32、33、35、36、37、38、40、41码元属于“天”信息,共占用10个码元。 IRIG—B码由位置识别标志、参考码元、码字和索引标志4种码元组成。 B码的位置识别标志脉宽为8 ms,每帧B码中有10个位置识别标志码元:P1、P2、…、P10。每10个码元有一个位置识别码,位置识别标志的重复率为码元速率的10%。   参考码元Pr脉宽也为8 ms,作用是识别帧的起始时刻,“准时”参考点为参考码元的前沿。   B码的二进制“1”和“0”的脉宽分别为5 ms和2 ms,是用于传递秒、分、时等重要信息的码元。     索引标志码元脉宽为2 ms,位于“秒”、“分”、“时”、“天”信息的十位和个位之间。   图6为本文B码的一帧数据示意图,后续实验就是对此帧数据进行解码,此帧数据代表的时间信息为:110天8时7分21秒。   2 FPGA解码 FPGA解码首先需要对码元进行识别,对脉冲计数,以脉冲下降沿作为计数结束。采用有限状态机对第0、1、2、…、99码元进行有序地解码,首先判断出参考码元,再根据5 ms和2 ms码元的位置提取出正确的时间信息。由于不同的系统可能采用不同解码时钟,为使系统有更好的重用性,需要对时钟频率进行归一化。 2.1 消除毛刺 在组合电路、反馈电路和计数器中都可能产生毛刺信号,往往一个毛刺信号会影响整个电子系统的稳定性。由于D触发器对毛刺信号不敏感,通常的处理方法是通过 D触发器对输入信号进行“过滤”,但这种方法有效的条件是毛刺不出现在D触发器时钟的上升沿,且持续时间不能维持1个时钟周期,如图7所示,否则,将会放大毛刺信号,对整个电子系统造成更不利影响。   若在P码元的5 ms处出现一个毛刺,而不作有效地毛刺处理,将会出现码元误判,甚至会导致整帧数据错误,影响各系统时间同步。输入信号经过图8所示的处理后,不利于系统的毛刺将被“剔除”,从而增强系统的稳定性。   当输入信号处于低电平时出现毛刺,图8的处理方法将会放大毛刺,但对于整个系统是没有影响的,因为本系统采用高电平计数的方式识别码元,当脉宽很窄时,便认为是毛刺干扰,舍去,比上升沿识别码元更简单且更具抗干扰性。这种毛刺处理方法,虽然引入了额外的组合电路,但根据输入信号的特点,是不会产生毛刺的。 2.2 对脉冲宽度进行计数和码元识别 本文采用的归一化时钟为1 MHz,脉宽2 ms、5 ms、8 ms的计数分别为2 000、5 000、8 000,由于脉宽不可能精确到某个值,所以需要放宽计数判别各个码元。计数在1500~2 500表示2 ms脉宽,计数在4 500~5 500表示5 ms脉宽,计数在7 500~8 500表示8 ms脉宽。输入信号i_DATA处于高电平时,开始计数,当时钟i_cLK采集到i_DATA的下降沿时,即停止计数,并以w_UP_DOWN信号作为脉冲结束标志。 2.3 提取“秒”、“分”等信息的状态机[!--empirenews.page--] STATE_IDL1表示处于检测码元,当检测出的码元脉宽为8 ms后,将进入STATE_IDL2。进入状态STATE_IDL2后,当第一个检测出的码元脉宽又是8 ms,则说明此刻检测出的Pr码元,即可以进入“秒”、“分”、“时”等后续检测中;若第一个检测出的码元脉宽不是8 ms,则说明此刻不是帧的起始时间,转入STATE_IDL1状态,继续检测。当进入“秒 ”检测状态(STATE_SEC),即可依次提取个位和十位信息,为增强系统稳定性,如果发现STATE_SEC状态中的第5个码元不是索引码元,状态便转入STATE_IDL1,否则继续检测“分”、“时”等信息。“分”、“时”、“天”信息的检测过程与“秒”同理。   3 Modelsim验证 根据B码帧结构可知,“秒”、“分”、“时”和“天”信息的第41个,也就是“秒”起始后大约41 ms时刻。从图10中可以清晰地看到大致在仿真时间4 1ms处出现o_FINI SH脉冲,o_FINISH作为解码结束标志,即验证了代码的正确性。从图10可知,解码出的时间是110天8时7分21秒。   4 结束语 在FPGA系统中,毛刺是影响整个电子系统稳定性的重要因素。本文中采用的去毛刺方法较好地解决了IRIG—B码解码中存在毛刺的问题,从而提高了系统的稳定性。由于增加了解码结束标志,本文的代码移植性更强。经过Modelsim仿真验证,该解码器功能正确,具有较高的可靠性。

    时间:2015-11-24 关键词: 解码 嵌入式开发 毛刺 irig—b码

  • HDMI前端设计与实现

    摘要:随着高清影音时代的到来,新的高清多媒体接口技术也渐趋成熟。本文研究了高清多媒体接口的编码和解码功能,并采用硬件描述语言实现高清多媒体接口规范定义的编解码功能。首先对高清多媒体接口的整体信道传输过程进行了分析和分解,并阐述了三个数据周期传输时间及其解码方式的不同。在此基础上对编解码功能进行了模块划分,采用分层及模块复用至顶向下的设计方法。最后通过NC—Verilog仿真工具仿真验证代码功能的正确性。 关键词:高清多媒体接口;编码;解码;至顶向下;仿真 0 引言 数字影音技术发展日新月异,多媒体视听领域正在进行着一场革命,随着生活水平的提高,普通影音己不能满足人们的需求,追求高清晰画质,立体感音质,已经成为新一代人追求时尚的一种诠释。 在过去相当长的一段时间,CRT(Cathode Ray Tube)为代表的模拟显示设备主导了整个显示设备市场。随着高清视频格式(720p/1080i/1080p)的确定,液晶电视、等离子电视等大尺寸数字化平板显示设备的发明和普及,传统模拟接口易受电磁干扰、传输速率低、带宽小、传输损耗大等缺点已经不能满足海量数据流传输等需求;同时,影视等行业对版权意识越来越重视,数据传输的加密变得愈发重要,传输更快更安全的全数字化接口代替模拟接口成为必然趋势。于是第一个行业支持的、无压缩的、全数字的音视频接口 —HDMI诞生了。 HDMI的全称是“High Definition Multimedia Interface高清多媒体接口”。2002年4月,来自电子电器行业的7家公司——日立、松下、飞利浦、Silicon Image、索尼、汤姆逊、东芝共同组建了HDMI高清多媒体接口组织HDMI founders(HDMI论坛),HDMI founders在2002年12月9号正式发布HDMI1.0版标准,标志着HDMI技术正式进入历史舞台。随着HDMI标准本身的发展,1.3a版本和2.0等后续版本也陆续推出,不仅性能更加强大,兼容性也更加出色。 在HDMI标准制定之初,继承了DVI标准中相对成熟且较容易实现的部分技术标准。整个传输原理依然是基于Silicon Image公司的TMDS(Transition Minimized Differential Sienaling)编码技术。 HDMI具有体积小、抗干扰强、兼容性好、智能连接、单线缆同时传输无压缩音视频等优势。因此,它已被广泛地应用到DVD、机顶盒等设备中,HDMI正在成为高清时代普及率最高、用途最广泛的数字接口。 1 HDMI概述 HDMI系统架构由信源端和接收端组成。如图1所示,HDMI提供四个独立的TMDS(Transition Minimized Differential Signaling)通信通道:三个数据信道和一个时钟信道,这些信道主要用于传递视频、音频和辅助数据。另外,HDMI提供一个VESADDC(Video Electronics Standards Association)(Display Data Channel)信道。DDC是用于配置和在一个单独的信源端和一个单独的接收端交换状态,读取接收端的E-EDID数据结构。CEC(Consumer Electronics Control)是一个可选信道,可选择在用户的各种不同的音视频产品中,为高端用户提供高水平的控制功能。可选择的HDMI以太网和音频返回(HEAC),在连接的设备中提供以太网兼容的网络数据和一个和TMDS相对方向的音频返回信道。   音频,视频和辅助数据都是在三个TMDS数据信道中相互交错传输。TMDS时钟,即视频像素速率传输时钟,在TMDS时钟信道中传输,它被接收端三个 TMDS信道作为一个频率参考,用于对三个TMDS数据信道的数据复原。在信源端,TMDS编码将每个TMDS数据的8bits数据转换成10bits的 DC-balanced数据,10bits的DC-balanced数据将以每个TMDS时钟周期串行地在差分线对上进行传输。 视频数据像素时钟的TMDS时钟上传递默认值为24位色深,视频数据还兼容30,36,48位像素的数据。更高的色深使用需要相应的更高的TMDS时钟率。视频格式TMDS时钟率低于25M可以运用像素复用发送的策略来进行传输。视频像素支持多种编码格式,可以是 RGB,YCbCr4:4:4,YCbCr4:2:2格式编码。 TMDS信道传输音频和辅助数据中,HDMI的信源端需要采取用包的格式来保证传输。为了保证音频和控制信号的高保真度,音频和辅助数据数据需要BCH纠错码的编码方式,且采取了一种10bits减少错误编码的特殊编码方式。基本的音频传输功能几乎包括所有的普通的立体声音频,在采样频率分别为 32KHz,44.1KHz和48KHz情况下的IEC60958L—PCM音频流。HDMI还可以传输采样频率高达192KHz,采用3到8个音频通道的音频流。HDMI同样可以传输采样频率高达24.576MHz的IEC61937压缩音频。HDMI同样可以传输2—8通道的OneBit音频或者是一种被称为DST的压缩的One Bit音频。 2 HDMI编码设计 本设计是基于HDMI 1.4版本的编解码设计。主要分为两个大模块设计,即HDMI TX编码模块和HDMI RX解码模块。TX编码模块主要实现把视频、音频数据通过编码传输给Rx解码模块。RX解码模块主要把视频、音频数据解码后传输给外置设备。 如图2所示,HDMI有三种处理数据的操作模式:视频数据周期,数据岛周期,控制周期。在视频数据周期,传输每一个有效的视频像素行。在数据岛周期中,音频和辅助数据使用一系列数据包来传输。在音频和视频周期的两个非控制周期之间要插入控制周期。   视频数据周期采用最小化差分传输编码(TMDS)的编码方式,对每个8bits传输信道进行编码,三个传输信道共24bits数据。 数据岛周期采用TMDS纠错编码(TERC4)的编码方式,每个4bits传输信道进行编码,三个传输信道共12bits数据。 控制周期采用最大化传输编码的编码方式,对每个2bits传输信道进行编码,三个传输信道共6bits。这6bits数据包括HSYNC、VSYNC、CTL0、CTL1、CTL2、CTL3。在每个控制周期的末尾有一个报文头,使用CTLx bits数据组成的preamble,指示下一个数据周期是视频周期还是数据岛周期。 每一个数据岛周期起始于前导保护带(Leading Guard Band),结束于后置保护带(Training Guard Band);而视频数据周期只始于前导保护带,没有后置保护带。保护边界两个特殊字符组成,设计目标是提供从控制周期到数据周期或从数据周期向控制周期转化的鲁棒决策。 下表2.3展示在数据传输中每种操作模式的编码类型。   2. 1 编码器TX模块 TX(信源端)发射模块,包括时钟模块(由Timing和Timing_dly两个模块组成)、以及编码模块。时钟模块主要为视频音频交错相传产生时钟,编码模块实现对视频音频数据编码传输。   2. 1.1 时钟模块 (1)Timing模块 Timing模块是HDMI编码器的基础,它产生720*480p、1280*720p、1920*1080i等视频格式的行信号hsync_pr、场信号vsync_pr、行无效信号hblnk_pr和场无效信号vblnk_pr。如图2所示,hsync_pr、vsync_pr分别为HSYNC、 VSYNC;hblnk_pr为每行前138 pixels置高位,vblnk_pr为每帧前42行和后3行共45行置高位(注:具体定义以CEA-861-D中规定的720*480p的标准视频格式为准)。 (2)Timing_dly模块 Timing_dly模块是HDMI高速数据传输的核心,按照TMDS通道的视频音频交错传输数据要求,分配视频数据、音频数据和辅助数据,以及控制数据的传输时间周期,并为编码模块提供控制信号。   主要端口定义: hsync_pr、vsync_pr;行信号和场信号。 aux_rdy:当输出是“1”,则外部数据缓存音频数据准备完毕,可以传输音频数据;否则,音频数据未完成打包,终止传输音频数据。 aux_admit:当输出是“1”,则传输音频数据;否则终止接受音频包数据。 ade、vde:分别表示传输音、视频数据标志位,为高时表示进入数据岛或视频数据周期。 2.1.2 encoder模块 timing模块采用TMDS编码、TERC4编码和最大化传输编码三种编码形式,对视频数据、音频数据包和辅助数据、控制数据编码传输。 视频像素数据的编码可分为两个阶段:第一个阶段是输入音频的8bits像素数据转换成9bits数据;第二阶段是把9bit数据转换成TMDS传输10bits。 实现的TMDS编码算法如图5所示。   D:输入8 bits视频数据。 cnt:计算编码数据中0和1个数的差值。若cnt为正值表示发送1的数量超过0的数量,负值则表示发送0的数量多于1的数量。cnt{t-1}表示相对于输入数据的前一个周期的cnt的值,cnt{t}表示本周期的值。 q_m:第一阶段的9 bits输出数据。 q_out:第二阶段的10 bits输出数据,即编码器输出值。 N1{x}:这个操作符返回参数x中的1的个数。 N0{x}:这个操作符返回参数x中的0的个数部分核心代码如下:     2.2 解码器RX模块 解码器模块较容易实现,只需依据preamble控制位判断接下来传输的数据类型,即音频或视频数据,然后解码即可。解码同样分两个阶段,如图5所示,第一阶段由10bits数据转为9bits数据,第二阶段由9bits数据转为8bits数据。 图6 TMDS解码原理   3 HDMI功能仿真验证 在HDMI功能验证采用分层验证法,根据Spec1.4的编码解码的要求,制定验证计划,设计各种激励,实现近百分之百的覆盖率。本文运用的工具是Cadence NC—Verilog,文中介绍部分验证计划,以及验证的结果。 3.1 时钟模块的功能仿真验证 按Spec1.4要求,给定仿真必需激励信号,仿真数据岛周期及视频数据周期的每个像素时钟的功能分布是否符合Spec1.4的要求。比如验证ctl[3:0]的正确性,如图4所示,在3个blanking、8个preamble、2个leading guard band的时钟周期之后,进入下一个状态,ctl[3:0]的值与状态所表示的值对比便可验证。 在验证数据岛周期:在ade_pr置高位后,经过4个blanking+8个preamble+2个leading guard band。packet传输结束后置低位。ade置高位进入data island period,再经过2个leading guard band+N个32位的packets+trialing guard band。trialing guard band后置低位。在8个preamble时,ctl[3:0]=4’b0101。 在验证视频数据周期时:vde_pr置高位后,经过4个blanking+8个preamble+2个leading guard band。video data传输结束后置低位。vde置高位进入video data period,再经过2个leading guard band+active video pixels。video data传输完后置低位。在8个preamble时,ctl[3:0]=4’b0001。 图7数据岛周期和视频数据周期仿真图   3.2 HDMI模块仿真 把时钟模块和encoder模块整合成TX模块,其中encoder模块分别实例为Encdr、Encdg、Encdb三个信道的编码模块。将TX和RX模块,即hdmi_encoder和hdmi_decoder,组合在一起仿真。 如图8所示,输入的音频、视频数据用random函数随机产生,且在固定的时间周期输入,将输出与输入对比,得出HDMI整个编解码模块是否正确。   如图9所示,第一组为7bits视频数据输入,第二组为编码后的10bits视频数据输出,第三组为解码后的7bits视频数据输出。视频数据编码需要三个时钟,解码需要两个时钟,所以每间隔五个时钟输入7bits数据等于输出的7bits数据,即从编码到解码一共需要五个时钟。   4 结论 进入21世纪,在带宽、音频、传输安全等方面具有优越性的HDMI的出现,满足了数字高清时代海量数据流传输的需求。本设计运用 verilog HDL实现HDMI编码及解码功能,通过写仿真测试激励及运用NC—Verilog工具仿真代码逻辑的正确性。从子模块、模块、系统仿真验证自底向上的方法来进行,最终根据仿真验证结果确认实现编解码功能。非常感谢芯珠微电子林泉工程师及梁文锋、黎伟莲、洪传练、杨家昌等同事的帮助,本设计的不足之处将在后续工作中改进。

    时间:2015-11-05 关键词: 解码 编码 仿真 高清多媒体接口 至顶向下

首页  上一页  1 2 3 4 5 6 7 8 9 10 下一页 尾页
发布文章

技术子站

更多

项目外包