单片机和嵌入式系统linux的区别6推荐随着嵌入式行业硬件平台的性能增强,项目需求和功能日益复杂,ARM公司推出的CORTEX-M3,更是让以往做单片机的工程师在芯片和技术选型面临两难选择,本专题将从芯片价格、整个系统的硬件软件设计及维护的成本等各个方面给您提供一个参考,并从技术角度分析单片机和带操作系统的系统的软件开发的异同点。●1.单片机与ARM等新处理器的价格比较●2.带操作系统与不带操作系统的软件开发的区别●2.1.驱动开发的区别●2.2.应用程序开发的区别1.单片机与ARM等新处理器的价格比较表1型号架构资源价格(元)AT89S518051最高频率33MHz4KBFlash128B内部RAM32个可编程IO引脚两个16bit的计数器一个UART口4SST89E564RD8051最高频率40MHz64KBFlash351KB内部RAM32个可编程IO引脚三个16bit的计数器一个UART口一个SPI接口STM32F103CORTEX-M3最高频率72MHz64KB或128BKFlash20KBSRAM80个可编程IO引脚2个12bit的ADC7通道DMA控制器标准调试口(SWD和JTAG)7个定时器USB接口2个I2C接口3个UART2个SPI接口21HI3510ARM9+DSP双核最高工作频率240MHz视频处理单元,支持多种协议的实时编解码图形处理单元视音频接口以太网接口DDR控制器80USB、UART、IrDA、I2C、SPI、GPIO等多种外设接口S3C2440ARM9最高工作频率400MHzSDRAM控制器LCD控制器4通道DMA控制器3个UART2个SPI1个I2C接口IIS音频接口SDHOST接口2个USB接口8个10bitADC摄像头接口Camera接口40从表1里面各种芯片的资源,大概就可以猜知它们的应用场合。51单片机通常被用来做一些比较简单的控制,比如采集信号、驱动一些开关。AT89S51的Flash只有4K,一个稍微复杂的程序就不止4K了。SST89E564RD是一种扩展的51单片机,它的Flash达到64KB,可以外接最多64KB的SRAM。在SST89E564RD上的程序可以写得更复杂一些,但是它对外的接口也比较少。CORTEX-M3系列的处理器,对外接口极其丰富,这使得它的应用面更广,但是限于它的Flash、内存还是比较小,一般不在上面运行操作系统,它算是一个性能非常突出的单片机。HI3510是海思半导体公司的一款用于监控设备的芯片,一般上面运行Linux系统,通过摄像头采集数据、编码,然后通过网络传输。另一端接收到数据之后,再解码。在上面运行的程序非常复杂,有漂亮的图片界面、触摸屏控制、数据库等等。对声音图像的编解码更是用到DSP核。S3C2440是一款通用的芯片,它与“高级单片机”STM32F103相比,多了存储控制器和NAND控制器──这使得可以外接更大的Flash、更大的内存;多了内存管理单元(MMU)──这使得它可以进行地址映身(虚拟地址、物理地址之间的映射)。可以在S3C2440上运行Linux系统,运行更大更复杂的程序。在具体工作中,怎么选择这些芯片呢?一句话:成本!进行任何产品的开发都要考虑性价比,一切应该从“成本”出发。成本不仅包括芯片的价格,也包括整个系统的硬件、软件设计及维护的难易。芯片价格可以在电子市场问到,也可以在上找到有卖这种芯片的柜台,然后电话咨询。基于不同的应用,处理器和其他外设的选择是要统一考虑的,如果要实现一个简单的U盘读写功能,那么可以选择带USB控制器的CORTEX-M3芯片,也可以选择8051外接一个USB控制器比如SL811,就看哪种方案成本更低。进行芯片选型时,必须基于整个系统来考虑。员工的偏好和知识结构也是一个很重要的因素,如果他对ATMEL的芯片比较熟,他就不会倾向于三星;如果他不会Linux等操作系统,那么选型时就不会有操作系统的概念。选择自己不熟悉的芯片和技术,最后的成本也可能更高。2.带操作系统与不带操作系统的软件开发的区别用通俗的话来说,一个处理芯片不运行操作系统,我们就把它称为单片机,而单片机编程就是写裸板程序,这个程序直接在板子上运行;相对的,另一种程序就是基于操作系统的程序,说得简单点就是,这种程序可以通过统一的接口调用“别人写好的代码”,在“别人的基础上”更快更方便地实现自己的功能。2.1.驱动开发的区别驱动开发的区别我总结有两点:能否借用、是否通用。2.1.1能否借用基于操作系统的软件资源非常丰富,你要写一个Linux设备驱动时,首先在网上找找,如果有直接拿来用;其次是找到类似的,在它的基础上进行修改;如果实在没有,就要研究设备手册,从零写起。而不带操作系统的驱动开发,一开始就要深入了解设备手册,从零开始为它构造运行环境,实现各种函数以供应用程序使用。举个例子,要驱动一块LCD,在单片机上的做法是:①首先要了解LCD的规格,弄清楚怎么设置各个寄存器,比如设置LCD的时钟、分辨率、象素②划出一块内存给LCD使用③编写一个函数,实现在指定坐标描点。比如根据x、y坐标在这块内存里找到这个象素对应的小区域,填入数据。基于操作系统时,我们首先是找到类似的驱动,弄清楚驱动结构,找到要修改的地方进行修改。下面是单片机操作LCD的代码:①初始化:voidTft_Lcd_Init(inttype){/**设置LCD控制器的控制寄存器LCDCON1~5*1.LCDCON1:*设置VCLK的频率:VCLK(Hz)=HCLK/[(CLKVAL+1)x2]*选择LCD类型:TFTLCD*设置显示模式:16BPP*先禁止LCD信号输出*2.LCDCON2/3/4:*设置控制信号的时间参数*设置分辨率,即行数及列数*现在,可以根据公式计算出显示器的频率:*当HCLK=100MHz时,*Rate=1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x*{(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x*{2x(CLKVAL+1)/(HCLK)}]*=60Hz*3.LCDCON5:*设置显示模式为16BPP时的数据格式:5:6:5*设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号):反转*半字(2字节)交换使能*/LCDCON1=(CLKVAL_TFT_3202408)|(LCDTYPE_TFT5)|\(BPPMODE_16BPP1)|(ENVID_DISABLE0);LCDCON2=(VBPD_32024024)|(LINEVAL_TFT_32024014)|\(VFPD_3202406)|(VSPW_320240);LCDCON3=(HBPD_32024019)|(HOZVAL_TFT_3202408)|(HFPD_320240);LCDCON4=HSPW_320240;//LCDCON5=(FORMAT8BPP_56511)|(HSYNC_INV9)|(VSYNC_INV8)|\//(HWSWP1);LCDCON5=(FORMAT8BPP_56511)|(HSYNC_INV9)|(VSYNC_INV8)|(VDEN_INV6)|\(HWSWP0);/**设置LCD控制器的地址寄存器LCDSADDR1~3*帧内存与视口(viewpoint)完全吻合,*图像数据格式如下:*|----PAGEWIDTH----|*y/x012239*0rgbrgbrgb...rgb*1rgbrgbrgb...rgb*1.LCDSADDR1:*设置LCDBANK、LCDBASEU*2.LCDSADDR2:*设置LCDBASEL:帧缓冲区的结束地址A[21:1]*3.LCDSADDR3:*OFFSIZE等于0,PAGEWIDTH等于(240*2/2)*/LCDSADDR1=((LCDBUFFER22)21)|LOWER21BITS(LCDBUFFER1);LCDSADDR2=LOWER21BITS((LCDBUFFER+\(LINEVAL_TFT_320240+1)*(HOZVAL_TFT_320240+1)*2)1);LCDSADDR3=(011)|(LCD_XSIZE_TFT_320240*2/2);/*禁止临时调色板寄存器*/TPAL=0;fb_base_addr=LCDBUFFER;bpp=16;xsize=320;ysize=240;}②描点:/**画点*输入参数:*x、y:象素坐标*color:颜色值*对于16BPP:color的格式为0xAARRGGBB(AA=透明度),*需要转换为5:6:5格式*对于8BPP:color为调色板中的索引值,*其颜色取决于调色板中的数值*/voidPutPixel(UINT32x,UINT32y,UINT32color){UINT8red,green,blue;switch(bpp){case16:{UINT16*addr=(UINT16*)fb_base_addr+(y*xsize+x);red=(color19)&0x1f;green=(color10)&0x3f;blue=(color3)&0x1f;color=(red11)|(green5)|blue;//格式5:6:5*addr=(UINT16)color;break;}case8:{UINT8*addr=(UINT8*)fb_base_addr+(y*xsize+x);*addr=(UINT8)color;break;}default:break;}}下面是在Linux的LCD驱动里修改的地方(arch\arm\mach-s3c2440\mach-smdk2440.c):/*320x240*/staticstructs3c2410fb_mach_infosmdk2440_lcd_cfg__initdata={.regs={.lcdcon1=S3C2410_LCDCON1_TFT16BPP|\S3C2410_LCDCON1_TFT|\S3C2410_LCDCON1_CLKVAL(0x04),.lcdcon2=S3C2410_LCDCON2_VBPD(1)|\S3C2410_LCDCON2_LINEVAL(239)|\S3C2410_LCDCON2_VFPD(5)|\S3C2410_LCDCON2_VSPW(1),.lcdcon3=S3C2410_LCDCON3_HBPD(36)|\S3C2410_LCDCON3_HOZVAL(319)|\S3C2410_LCDCON3_HFPD(19),.lcdcon4=S3C2410_LCDCON4_MVAL(13)|\S3C2410_LCDCON4_HSPW(5),.lcdcon5=S3C2410_LCDCON5_FRM565|S3C2410_LCDCON5_INVVLINE|S3C2410_LCDCON5_INVV|S3C2410_LCDCON5_INVVDEN|S3C2410_LCDCON5_PWREN|S3C2410_LCDCON5_HWSWP,},.gpccon=0xaaaa56aa,.gpccon_mask=0xffffffff,.gpcup=0xffffffff,.gpcup_mask=0xffffffff,.gpdcon=0xaaaaaaaa,.gpdcon_mask=0xffffffff,.gpdup=0xffffffff,.gpdup_mask=0xffffffff,.fixed_syncs=1,.type=S3C2410_LCDCON1_TFT,.width=320,.height=240,.xres={.min=320,.max=320,.defval=320,},.yres={.max=240,.min=240,.defval=240,},.bpp={.m