搜索
bottom↓
回复: 2

【阿莫AVR芯片检测系列文章2】AVR IO 端口的合格性扫描检查(v1.0)

[复制链接]
头像被屏蔽

出0入0汤圆

发表于 2008-6-11 08:20:41 | 显示全部楼层 |阅读模式
注:ouravr.com 内部独家资料,不允许转载,不允许应用于商业用途。

我写软件,习惯先规划好流程图,然后才动手的 :)

我们的拆机AVR芯片,均是经过以下的IO端口扫描程序,检查至少2000次后,才出货,以确保我们的拆机AVR芯片能有100%的合格率。

检查的思路,是将JTAG的熔丝位取消,将PB6作为检查正常的输出(绿灯),PB7作为出错的红灯及蜂鸣器长响输出。

将两个两个IO组成一组。并且以270K电阻接地。 然后两只IO连接在一起(中间各用1K的电阻隔离)。
开始均作为输入,使用上拉电阻编程与接地电阻,产生0、1状态,自己读自己的输入是否正常。
然后一个作为输入,另一个作为输出,以上拉电阻编程与接地电阻,分别读取0,1。
然后换成一个作为输出,另一个作为输入,以上拉电阻编程与接地电阻,分别读取0,1。
以上的过程重复2000次。

如果全部执行通过,绿灯闪两下后就长亮。
如果执行过程中有任何出错,立即停止运行,红灯亮并且发出声音报警。

本程序经过了长时间及超过10K芯片的检测,证实性能可靠稳定。

   checkIO(AVRPA0,AVRPA1);
   checkIO(AVRPA2,AVRPA3);
   checkIO(AVRPA4,AVRPA5);
   checkIO(AVRPA6,AVRPA7);

   checkIO(AVRPB0,AVRPB1);
   checkIO(AVRPB2,AVRPB3);
   checkIO(AVRPB4,AVRPB5);
   //-----checkIO(AVRPB6,AVRPB7); //用于输出,6绿灯,7红灯

   checkIO(AVRPC0,AVRPC1);
   checkIO(AVRPC2,AVRPC3);  //jtag  
   checkIO(AVRPC4,AVRPC5);  //jtag
   checkIO(AVRPC6,AVRPC7);

   checkIO(AVRPD0,AVRPD1);
   checkIO(AVRPD2,AVRPD3);
   checkIO(AVRPD4,AVRPD5);
   checkIO(AVRPD6,AVRPD7);   




(原文件名:1.JPG)


(原文件名:2.jpg)


(原文件名:SNAG-0031.jpg)


/******* *********************************************************************
*
* This file is used to test IO.
*
* - Compiler:           GNU GCC
* - Supported devices:  M16,M32
* - author              Armok / www.OurAvr.com / 鸣谢kingofkings网友帮忙做了函数封装的工作
*
* - Last updated        2008-06-05,14:11
*****************************************************************************/

#include <avr/io.h>

//宏定义管脚ID号
//进行如下分配:PA0~PA7:00~07,其中十位上是组号,个位上是管脚号
#define AVRPA0 00
#define AVRPA1 01
#define AVRPA2 02
#define AVRPA3 03
#define AVRPA4 04
#define AVRPA5 05
#define AVRPA6 06
#define AVRPA7 07

#define AVRPB0 10
#define AVRPB1 11
#define AVRPB2 12
#define AVRPB3 13
#define AVRPB4 14
#define AVRPB5 15
#define AVRPB6 16
#define AVRPB7 17

#define AVRPC0 20
#define AVRPC1 21
#define AVRPC2 22
#define AVRPC3 23
#define AVRPC4 24
#define AVRPC5 25
#define AVRPC6 26
#define AVRPC7 27

#define AVRPD0 30
#define AVRPD1 31
#define AVRPD2 32
#define AVRPD3 33
#define AVRPD4 34
#define AVRPD5 35
#define AVRPD6 36
#define AVRPD7 37

void delay_us(int time)
     {
         for(;time>1;time--);
         }
void delay_ms(unsigned int time)
         {
         while(time!=0)
                                    {
                                   delay_us(884);
                                    time--;
                                   }
         }

void green_led(void);
void red_led(void);
void delay_nop(void);
void IOSearch(unsigned char IOID[2],unsigned char IOresult[3]);//IO定位程序
void IOdetect(unsigned char IOaddr[3],unsigned char IOtestID0,unsigned char IOtestID1);//IO检测程序
void checkIO(unsigned char IO0,unsigned char IO1);//IO检测主函数
void CoreTest();
int main()
{
SFIOR&=~(1<<2);  //SFIOR的PUD是0时,上拉电阻才有效。缺省是0。所以这句话可以不要的。

//PA,PB,PC,PD设置成输入,上拉电阻启用
   DDRA=0x00;  
   PORTA=0xff;
   DDRB=0x00;
   PORTB=0xff;
   DDRC=0x00;
   PORTC=0xff;
   DDRD=0x00;
   PORTD=0xff;

   DDRB|=0b11000000;  //PB6是绿灯,PB7是红灯,先将灯熄灭
   //PORTB|=0B11000000;
   //delay_ms(100);
   PORTB&=0b00111111;
   
int reply_times = 2000; //检测次数


while (reply_times>1)
{
   checkIO(AVRPA0,AVRPA1);
   checkIO(AVRPA2,AVRPA3);
   checkIO(AVRPA4,AVRPA5);
   checkIO(AVRPA6,AVRPA7);

   checkIO(AVRPB0,AVRPB1);
   checkIO(AVRPB2,AVRPB3);
   checkIO(AVRPB4,AVRPB5);
   //-----checkIO(AVRPB6,AVRPB7); //用于输出,6绿灯,7红灯

   checkIO(AVRPC0,AVRPC1);
   checkIO(AVRPC2,AVRPC3);  //jtag
   checkIO(AVRPC4,AVRPC5);  //jtag
   checkIO(AVRPC6,AVRPC7);

   checkIO(AVRPD0,AVRPD1);
   checkIO(AVRPD2,AVRPD3);
   checkIO(AVRPD4,AVRPD5);
   checkIO(AVRPD6,AVRPD7);  

   reply_times --;
}



//全部执行完成,绿灯,指示正常。

green_led();
delay_ms(500);
PORTB&=~(1<<6);

delay_ms(500);
green_led();
delay_ms(500);
PORTB&=~(1<<6);
delay_ms(500);
//green_led();
//delay_ms(500);
//PORTB&=~(1<<6);
//delay_ms(500);


}

void green_led(void)
{
   PORTB|=(1<<6);
}

void red_led(void)
{

   PORTB|=(1<<7);
   check_end:;
   goto check_end;
}
//IO定位程序
/*
为了便于封装程序,操作IO采用地址传递的方式,但是首先需要对IO的组别(ABCD) 和管脚号(0~7)进行分类
在文件的宏定义中,我对M16的IO进行如下分配:PA0~PA7:00~07,其中十位上是组号,个位上是管脚号,通过
IOSearch函数来进行分类处理,输入为需要测试的两个IO号(这个值通过checkIO检测主函数传入) 并通过操作
IOresult数组将数据传出
*/
/*
传入:IOID[2]测试IO号
交换:IOresult[3]处理结果,IOresult[0]放组号,IOresult[1]放测试IO管脚号,IOresult[2]放另一个测试IO管脚号
*/
void IOSearch(unsigned char IOID[2],unsigned char IOresult[3])
        {
        IOresult[0] = IOID[0]/10;               //取十位数,为组号
        IOresult[1] = IOID[0]-(10*IOresult[0]);//取个位数,为测试IO管脚号
        IOresult[2] = IOID[1]-(10*IOresult[0]);//取个位数,为另一个测试IO管脚号
        }
/*
举例:
   define AVRPD2 32
   define AVRPD3 33

   IOID[2]={32,33};
   IOresult[0]=32/10=3
   IOresult[1]=32-10*3 = 2;
   IOresult[0]=33-10*3 = 3;   


*/


//IO检测程序
/*
这个程序是实际操作检测的过程函数
检测过程请参考IO检测流程图
*/
/*
传入:unsigned char IOaddr[3] 测试IO组别的操作变量地址(DDRX PINX PORTX)
      unsigned char IOtestID0,unsigned char IOtestID1 传入的两个测试管脚号
*/

void IOdetect(unsigned char IOaddr[3],unsigned char IOtestID0,unsigned char IOtestID1)
        {
        unsigned char *IODDRX  = IOaddr[0];//通过指针将DDRX地址取出
        unsigned char *IOPINX  = IOaddr[1];//通过指针将PINX地址取出
        unsigned char *IOPORTX = IOaddr[2];//通过指针将PORTX地址取出
        void setDDRX(unsigned char IOtestID)//置位DDRX某一位,传入:unsigned char IOtestID 需要操作的管脚号
                {
        *IODDRX |= (1<<IOtestID);
                }
    void clrDDRX(unsigned char IOtestID)//清0 DDRX某一位,传入:unsigned char IOtestID 需要操作的管脚号
                {
        *IODDRX &= ~(1<<IOtestID);
                }
    void setPORTX(unsigned char IOtestID)//置位PORTX某一位,传入:unsigned char IOtestID 需要操作的管脚号
                {
        *IOPORTX |= (1<<IOtestID);
                }
    void clrPORTX(unsigned char IOtestID)//清0 PORTX某一位,传入:unsigned char IOtestID 需要操作的管脚号
                {
        *IOPORTX &= ~(1<<IOtestID);
                }
    //读测试IO某一位上的电平值
        //传入:unsigned char IOtestID 需要操作的管脚号
        //传出:测试IO的电平值
        unsigned char ReadIO(unsigned char IOtestID)
                {
                 return ((*IOPINX >> IOtestID)&0x01);
                }
    //检测过程请参考IO检测流程图
        clrDDRX(IOtestID0);
    clrDDRX(IOtestID1);
        clrPORTX(IOtestID0);
    clrPORTX(IOtestID1);
        delay_nop();
        if ((ReadIO(IOtestID0) != 0)&&(ReadIO(IOtestID1) != 0)) red_led();
        else if((ReadIO(IOtestID0) == 0)&&(ReadIO(IOtestID1) != 0)) red_led();
        else if((ReadIO(IOtestID0) != 0)&&(ReadIO(IOtestID1) == 0)) red_led();

    clrDDRX(IOtestID0);
    clrDDRX(IOtestID1);
        setPORTX(IOtestID0);
    setPORTX(IOtestID1);
        delay_nop();
        if ((ReadIO(IOtestID0) != 1)&&(ReadIO(IOtestID1) != 1)) red_led();
        else if ((ReadIO(IOtestID0) == 1)&&(ReadIO(IOtestID1) != 1)) red_led();
        else if ((ReadIO(IOtestID0) != 1)&&(ReadIO(IOtestID1) == 1)) red_led();

    setDDRX(IOtestID0);
    clrDDRX(IOtestID1);
        setPORTX(IOtestID0);
    clrPORTX(IOtestID1);
        delay_nop();
        if (ReadIO(IOtestID1) != 1) red_led();

        setDDRX(IOtestID0);
    clrDDRX(IOtestID1);
        clrPORTX(IOtestID0);
    setPORTX(IOtestID1);
        delay_nop();
        if (ReadIO(IOtestID1) != 0) red_led();

        setDDRX(IOtestID1);
    clrDDRX(IOtestID0);
        setPORTX(IOtestID1);
    clrPORTX(IOtestID0);
        delay_nop();
        if (ReadIO(IOtestID0) != 1) red_led();

        setDDRX(IOtestID1);
    clrDDRX(IOtestID0);
        clrPORTX(IOtestID1);
    setPORTX(IOtestID0);
        delay_nop();
        if (ReadIO(IOtestID0) != 0) red_led();

        //green_led();

        }
//IO检测主函数
/*
IO检测主函数,这个函数将完成所有的检测工作。
传入两个测试IO号,IO号在宏定义中命名,命名方式为:AVRPXY其中X为组号,Y为管脚号
*/
/*
传入unsigned char IO0,unsigned char IO1 两个测试管脚号
*/       
void checkIO(unsigned char IO0,unsigned char IO1)
        {
        unsigned char IOaddr[4][3] = {{&DDRA,&PINA,&PORTA},{&DDRB,&PINB,&PORTB},{&DDRC,&PINC,&PORTC},{&DDRD,&PIND,&PORTD}};
    //为了便于封装,使用了操作IO地址的方式,实际上DDRX之类的变量在头文件中也是操作地址,这个数组就是把所有的
        //IO地址取出来便于传递和调用。
        unsigned char IOID[2] = {IO0,IO1};//对传递进来的测试IO管脚号赋值给一个一维数组,便于操作
        unsigned char IOtestID[3];//传递IO管脚参数的数组
        IOSearch(IOID,IOtestID);//调用IO管脚定位程序
    IOdetect(IOaddr[IOtestID[0]],IOtestID[1],IOtestID[2]);//IO检测程序
        }
void delay_nop(void)
{
   asm("nop");
   asm("nop");
   asm("nop");

}

出0入0汤圆

发表于 2008-6-11 11:03:37 | 显示全部楼层
沙发吗?顶!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-2 22:51

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表