打印

我想搞清楚什么是“初始化”

[复制链接]
5639|26
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
iC921|  楼主 | 2009-8-4 19:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
程序匠人| | 2009-8-4 21:23 | 只看该作者
是问单片机的初始化吗?

初始化,就是让系统建立一个初始的工作环境。

包括:
1、IO口的设置。输入、输出、高电平、低电平、内部上拉、下拉。等等
2、功能模块的设置。比如,ADC,PWM,LCD驱动,中断等等。这些模块都要先设置好才能用。
3、数据和参数的初始化。比如,你有一个实时时钟系统,那么可能需要在上电时,先把时分设置为“12:00”
4、开机自检。有些产品具有开机自动检测故障功能。一般也是放在初始化程序里面。
5、初始化,有时还分为冷启动和热启动,分别走不同的分支,执行不同的初始化动作
6、其它。。。。。

使用特权

评论回复
板凳
程序匠人| | 2009-8-4 21:25 | 只看该作者
以下是一个初始化程序实例:
(仅供参考)



//--------------------------------------------------------
//初始化程序
//--------------------------------------------------------
void init(void)
{
        tU08 i ;

        //====IO口设置
        PORTA = 0B00111110 ;                //设置PORTA口电平
        TRISA = 0B00000001 ;                //设置PORTA口输入/输出态

        PORTB = 0B11111110 ;                //设置PORTB口电平
        TRISB = 0B00000001 ;                //设置PORTB口输入/输出态

        PORTC = 0B01110111 ;                //设置PORTC口电平
        TRISC = 0B10000000 ;                //设置PORTC口输入/输出态  (串行接收口RX(RC7)设置为输入态)

        //====寄存器初始化

        //====参数初始化
        DISP_TIME_SET = (65536-1000) ;        //单列显示时间设置值

        DISP_LINE = DISP_LINE_ADJ ;        //显示列计数器(0~179)=校正值
        TIMR1_JSQ = 0 ;                        //TIMR1溢出计数器 = 0

        MOTOR_ST_FLAG = 1 ;                //电机正常开启状态标志=1(0=关闭,1=开启)
        SET_EN_FLAG = 0 ;                //设置使能标志=0(0=禁止,1=使能)

        DISP_MODE = 0 ;                        //显示状态(0~7)
        SET_MODE = 0 ;                         //设置状态(0~5)

        MD_CH_FLAG = 1 ;                //显示的状态被切换标志=1

        TIME_H = 12 ;                         //时钟"时"(0~23)
        TIME_M  = 0 ;                         //时钟"分"(0~59)
        TIME_S  = 0 ;                          //时钟"秒"(0~59)
        TIME_MS = 0 ;                          //时钟"毫秒"(0~49) (每过20ms,+1)
        TIME_US = 0 ;                          //时钟"微秒"(0~24) (每过800us,+1)
        T_20MS_FLAG = 0 ;                //20毫秒定时溢出标志(0=未溢出,1=溢出)

        NEW_DISP_EN_FLAG = 1 ;                //显示刷新使能标志=1(0=禁止,1=使能)

        COMM_DELAY_JSQ = 0 ;            //通讯延时计数器=0
        COMM_END_FLAG = 0 ;                //通信接收结束标志=0
        COMM_PUT_PTR = 0 ;                //接收数据存放指针=0

        SP_RUN = 0 ;                        //闹铃时间运行值(0~99分)

        NO_KEY_JSQ = 0 ;                 //无按键计数器=0(每1S+1)

        //温度历史纪录队列初始化
        for ( i=0 ; i<24; i++)
        {
                TEMP_LS_QUEUE[i] = 25 ;
        }
        TEMP_LSPJ=25 ;


        //====EEPROM中参数初始化
        eeprom_init() ;
       
        //====INT口,WDT,TIMR0设置
        OPTION = 0B10001111 ;                //预分频器分配给WDT; 预分频=1:128; TMR0时钟源=内部指令周期计数; PORT内部上拉禁止; NT口触发边沿=下降沿;
        TMR0 = 256-250 ;                //TMR0赋初值

        //====TIMR1设置
        T1CON = 0 ;                        //TMR1控制寄存器=0
        TMR1HL = DISP_TIME_SET ;        //TMR1赋初值

        T1CKPS1 = 0 ;
        T1CKPS0 = 0 ;                        //预分频系数=1:1
        T1OSCEN = 0 ;                        //关闭内部振荡器电路
        T1SYNC = 0 ;                        //同步计数模式
        TMR1CS = 0 ;                        //时钟源=内部指令周期计数
        TMR1ON = 1 ;                        //计数使能

        //====TIMR2设置
        PR2 = ( 225-1 ) ;                //周期控制寄存器=225
        T2CON = 0B00000111 ;                //预分频=1:16,后分频=1:1,开启TIMR2
       
        //====串口设置(说明:接收使能,发送使能(用于蜂鸣器控制),异步通讯,波特率=1200,数据位=8bit,停止位=1bit,无校验位)
        SPBRG = 233 ;                        //波特率=fosc/64(SPBRG+1)=18000000/(64*(233+1))=1201.92   

        TXSTA = 0B00100000 ;                //异步低速方式,发送8bit数据,发送使能
        RCSTA = 0B10010000 ;                //串口工作使能,接收8bit数据,连续接收允许
       
        //====ADC设置
        #if        ChipType == 886
                ANSEL = 0B00000001 ;                //AN0设置为AD口               
                ANSELH = 0B00000000 ;                //其它口设置为IO口       
                ADCON1 = 0B00000000 ;                //左对齐;参考电压=VSS,VDD
                ADCON0 = 0B11000001 ;                //ADC时钟源=自带RC;通道选择AN0;启动AD模块电源
        #elif        ChipType == 876
                ADCON1 = 0B00001110 ;                //选择AN0通道为模拟口,其它通道为数字口
                ADCON0 = 0B11000001 ;                //ADC时钟源=自带RC;通道选择AN0;启动AD模块电源
        #endif

        ADGO = 1 ;                        //启动ADC

        //====中断使能
        INTCON = 0 ;                        //中断控制寄存器=0
        PIE1 = 0 ;
        PIE2 = 0 ;

        INTE = 1 ;                         //使能INT中断
        //T0IE = 1 ;                        //TMR0中断
        TMR1IE        = 1 ;                        //TMR1中断
        TMR2IE        = 1 ;                        //TMR2中断
       
        TXIE = 0 ;                        //串口发送中断
        RCIE = 1 ;                        //串口接收中断
       
        PEIE = 1 ;                        //外设中断
        GIE = 1 ;                        //全局中断
       
        //====上电蜂鸣器鸣叫
        __sp_cnt__(SP_JSQ_RST)                //蜂鸣器鸣叫
}

使用特权

评论回复
地板
平常人| | 2009-8-4 22:04 | 只看该作者
从程序设计角度讲:程序的"初始化"就是把程序中所有的变量设置为一个已知状态,使得各个变量的数值之间的关系保持一致。

一般的"初始化"步骤是把所有变量清'0'。对于硬件的"初始化"就是把硬件模块设置为就绪状态。

使用特权

评论回复
5
928315| | 2009-8-4 23:27 | 只看该作者
PORTA = 0B00111110 ;                //设置PORTA口电平
  
为什么用这种写法?而不是PORTA =0X37?编译后执行快?

使用特权

评论回复
6
程序匠人| | 2009-8-4 23:45 | 只看该作者
PORTA = 0B00111110 ;                //设置PORTA口电平
  
为什么用这种写法?而不是PORTA =0X37?编译后执行快?
928315 发表于 2009-8-4 23:27


因为这个是IO口,使用二进制,能够更直观地看清楚每个位的设置。
当然,有些编译器不支持二进制写法,就没有办法了。
执行速度方面,用二进制、十进制、十六进制,都是一样的。

使用特权

评论回复
7
iC921|  楼主 | 2009-8-5 06:52 | 只看该作者
谢谢,有点儿象擦黑板。

再问1:初始化是不是单片机开始运行后只进行一次呢?当然,发生意外(如WTD动作)除外。

使用特权

评论回复
8
呆板书生| | 2009-8-5 07:07 | 只看该作者
初始化只是一个动作,通常每次进程的开始,进程用到的所有资源都要进入预备状态,这个动作就叫初始化。

初始化要进行多少次,视乎实际的需要,比如串口要初始化,一般只是一次,但如果某个应用是要串口使用多种波特率的,那这个串口就要根据不同的情况进行初始化。

使用特权

评论回复
9
程序匠人| | 2009-8-5 08:25 | 只看该作者
8楼已经回答了7楼的问题。基本上把我要说的都说了。

使用特权

评论回复
10
平常人| | 2009-8-5 08:30 | 只看该作者
擦黑板的说法还算靠谱。

"初始化"IC921还真不容易,哈哈哈哈。。。。。。。。。

使用特权

评论回复
11
程序匠人| | 2009-8-5 08:35 | 只看该作者
我觉得擦黑板的说法还不够全面。
如果所有参数的默认值都是零,那有点像“擦黑板”。但有时默认值未必是零。

应该说,初始化相当于老师在上课前在黑板上“预先把教学内容写在黑板上”的那个动作

使用特权

评论回复
12
winhiwang| | 2009-8-5 08:48 | 只看该作者
1.初始化就是把所有用到的资源(RAM,寄存器,IO口)设定一个初值.

2.不要相信所谓的默认值,MCU运行情况很复杂,所有状态和寄存器都有可能被意外修改.

3.系统上电,复位,WDT溢出发现程序异常等情况都需要进行初始化,不过不同情况下的初始化要不同对待. 对于一些控制设备的IO口不能轻易的初始化,因为容易造成误动作,要谨慎对待. 一些重要的IO口状态,可以保存在几个RAM中,保证异常时能正确回到对应的状态.

使用特权

评论回复
13
bear15888| | 2009-8-5 09:26 | 只看该作者
初始化,言外之意就是在做一件事情之前的准备工作!让事情朝你所想要的方向发展。

使用特权

评论回复
14
古道热肠| | 2009-8-5 10:32 | 只看该作者
这个问题有此泛指,不好回答,如果是指嵌入式系统,上面的诸位的回答是问题的正解.
如果扯到其它的,比如您问开启PC要做那些初始化工作.那就是答非所问了.

使用特权

评论回复
15
SeaSun| | 2009-8-5 13:18 | 只看该作者
我知道什么,也很想回答,但是找不着词儿,不知怎么说

使用特权

评论回复
16
iC921|  楼主 | 2009-8-8 19:44 | 只看该作者
基本了解,谢谢各位,俺初步被初始化了!

8楼和12楼解答得很详细,匠人给我最多,非常感谢!总的来说,是不是可以说有全局初始化和(执行)任务(前)初始化的区别?

派生问题:
对于一些控制设备的IO口不能轻易的初始化,因为容易造成误动作,要谨慎对待. 一些重要的IO口状态,可以保存在几个RAM中,保证异常时能正确回到对应的状态.

此处所说的谨慎,能不能举一些例子?为什么建议“一些重要的IO口状态,可以保存在几个RAM中”?

使用特权

评论回复
17
iC921|  楼主 | 2009-8-8 19:44 | 只看该作者
这几天上不了网,回复迟了些,请各位谅解!

使用特权

评论回复
18
程序匠人| | 2009-8-8 20:06 | 只看该作者
基本了解,谢谢各位,俺初步被初始化了!

8楼和12楼解答得很详细,匠人给我最多,非常感谢!总的来说,是不是可以说有全局初始化和(执行)任务(前)初始化的区别?

派生问题:
此处所说的谨慎,能不能举一些例子 ...
iC921 发表于 2009-8-8 19:44


分两点来说:
1、全局初始化和任务初始化。如果某一个功能,在整个系统中是恒久不变的,那么可以全局初始化,即上电时就初始化。但是有些功能在上电时不开,等到满足特定条件后才打开。那么可以理解为是任务初始化

2、至于你引用的那个问题,是另一个问题。处于提高系统鲁棒性考虑,一些IO口或标志位需要动态实时刷新,以便“纠正”一些可能发生的错误。

使用特权

评论回复
19
iC921|  楼主 | 2009-8-8 22:46 | 只看该作者
哈哈,匠人回答这种问题好轻松!!

使用特权

评论回复
20
wlawei| | 2009-8-9 09:34 | 只看该作者
初始化就是单片机在进入工作状态前需要做的准备工作,具体准备工作需要做什么,前面的都已经介绍的很全面了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

781

主题

17306

帖子

13

粉丝