【DG】物理DG中LNSn、NSS、NSA进程

DG】物理DG中主库的LNSnNSSNSA进程的比较


  1. BLOG文档结构图


  1. 前言部分


  1. 导读和注意事项

各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~:

检查物理DG是否正常的常用SQL

日志传输进程LNSn、NSS、NSA的区别

日志传输的2种方式:lgwr和arch,10g和11g有了变化

dg的架构图



Tips:

① 本文在ITpub(http://blog.itpub.net/26736162)和博客园(http://www.cnblogs.com/lhrbest)有同步更新

② 文章中用到的所有代码,相关软件,相关资料请前往小麦苗的云盘下载(http://blog.itpub.net/26736162/viewspace-1624453/

③ 若文章代码格式有错乱,推荐使用搜狗、360或QQ浏览器,也可以下载pdf格式的文档来查看,pdf文档下载地址:http://blog.itpub.net/26736162/viewspace-1624453/

本篇BLOG中命令的输出部分需要特别关注的地方我都用灰色背景和粉红色字体来表示,比如下边的例子中,thread 1的最大归档日志号为33thread 2的最大归档日志号为43是需要特别关注的地方;而命令一般使用黄色背景和红色字体注;对代码或代码输出部分的注释一般采用蓝色字体表示


本文如有错误或不完善的地方请大家多多指正,ITPUB留言或QQ皆可,您的批评指正是我写作的最大动力。



  1. 相关参考文章链接

关于dg的安装和一些高级应用参考:

DATAGUARD DG 系列

 

【推荐】 【故障处理】DG归档丢失的恢复

http://blog.itpub.net/26736162/viewspace-2087473/

DG】主rac + rac dg 部署

http://blog.itpub.net/26736162/viewspace-1991449/

【推荐】 【DATAGUARD】物理dg配置客户端无缝切换 (八.4)--ora-16652 和 ora-16603错误

http://blog.itpub.net/26736162/viewspace-1811947/

【推荐】 【DATAGUARD】物理dg配置客户端无缝切换 (八.3)--客户端TAF 配置

http://blog.itpub.net/26736162/viewspace-1811944/

【推荐】 【DATAGUARD】物理dg配置客户端无缝切换 (八.2)--Fast-Start Failover 的配置

http://blog.itpub.net/26736162/viewspace-1811936/

【推荐】 【DATAGUARD】物理dg配置客户端无缝切换 (八.1)--Data Guard Broker 的配置

http://blog.itpub.net/26736162/viewspace-1811839/

【推荐】 【DATAGUARD】物理dg在主库丢失归档文件的情况下的恢复(七)

http://blog.itpub.net/26736162/viewspace-1780863/

DATAGUARD】物理dg的failover切换(六)

http://blog.itpub.net/26736162/viewspace-1753130/

DATAGUARD】物理dg的switchover切换(五)

http://blog.itpub.net/26736162/viewspace-1753111/

【推荐】 【DATAGUARD】 将11g物理备库转换为Snapshot Standby

http://blog.itpub.net/26736162/viewspace-1525548/

【推荐】 【DATAGUARD】 基于同一个主机建立物理备库和逻辑备库 (四)--添加一个物理dg节点

http://blog.itpub.net/26736162/viewspace-1484878/

【推荐】 【DATAGUARD】 基于同一个主机建立物理备库和逻辑备库 (三)

http://blog.itpub.net/26736162/viewspace-1481972/

【推荐】 【DATAGUARD】 基于同一个主机建立物理备库和逻辑备库(二)

http://blog.itpub.net/26736162/viewspace-1448207/

【推荐】 【DATAGUARD】 基于同一个主机建立物理备库和逻辑备库(一)

http://blog.itpub.net/26736162/viewspace-1448197/



  1. 本文简介

同事说dg不能同步,让我帮忙看看,我用自己写的2个视图查看了下,首先发现主库没有常见的LNSn进程,下意识的认为主库这个进程没有启动,需要切换日志唤醒LNSn进程,事实上也这样做了,(alter system set log_archive_dest_state_2='defer'; alter system switch logfile; alter system set log_archive_dest_state_2='enable'; alter system switch logfile;),切换后发现日志可以正常传输了,但是主库还是看不到LNSn这个进程,于是找找资料,深入的研究了一下这个问题。

在读完整个文章后,大家就会了解我这里碰到的问题,说明配置的时候不是采用的异步方式,而小麦苗后来也的确去查看了下,采用的是LGWR SYNC的方式,在读完这篇文章后大家对这个问题就非常明朗了。

  1. 相关知识点扫盲(摘自网络+个人总结)

    1. DG架构图

下图是小麦苗绘制的dg结构图,对于里边的redo buffer到底如何传递到LNSn,众说纷纭,10g和11g也有不同,但这个不是我们今天讨论的内容,详细点的资料可以参考:http://www.itpub.net/thread-1841337-1-1.html,我们讨论并实验LNSn、NSS、NSA进程在10g和11g的中表现形式。


  1. DG日志传输

DG架构可以按照功能分成3个部分:

1) 日志发送(Redo Send)

2) 日志接收(Redo Receive)

3) 日志应用(Redo Apply)


我们今天着重来讲讲这里的日志发送的部分。

Primary Database 运行过程中,会源源不断地产生Redo 日志,这些日志需要发送到Standy Database。 这个发送动作可以由Primary Database 的LGWR 或者ARCH进程完成, 不同的归档目的地可以使用不同的方法,但是对于一个目的地,只能选用一种方法。 选择哪个进程对数据保护能力和系统可用性有很大区别。  

如果你配置一个目的地来使用 LGWR 进程, 但是由于某些原因 LGWR 进程变得无法归到目的地了,则重做传输将会回复到使用 ARCn 进程来完成归档操作。

alter system set log_archive_dest_2='SERVICE=tns_mydgwl LGWR ASYNC db_unique_name=mydgwl valid_for=(ONLINE_LOGFILES,PRIMARY_ROLE)' sid='*';

alter system set log_archive_dest_2='SERVICE=tns_mydgwl db_unique_name=mydgwl valid_for=(ONLINE_LOGFILES,PRIMARY_ROLE)' sid='*';

若不写传输进程和模式的话,11g下默认为LGWR ASYNC方式,10g为ARCH SYNC模式。


  1. 使用ARCH 进程

1)Primary Database 不断产生Redo Log,这些日志被LGWR进程写到联机日志。

2)当一组联机日志被写满后,会发生日志切换(Log Switch),并且会触发本地归档,本地归档位置是采用 LOG_ARCHIVE_DEST_1='LOCATION=/path' 这种格式定义的。如:alter system set log_archive_dest_1 = 'LOCATION=/u01/arch' scope=both;

3)完成本地归档后,联机日志就可以被覆盖重用。

4)ARCH 进程通过Net 把归档日志发送给Standby Database的RFS(Remote File Server) 进程。

5)Standby Database 端的RFS 进程把接收的日志写入到归档路径中。

6)Standby Database 端的MRP(Managed Recovery Process)进程(Redo Apply)或者LSP 进程(SQL Apply)在Standby Database上应用这些日志,进而同步数据。

说明:

逻辑Standby接收后将其转换成SQL语句,在Standby数据库上LSP进程执行SQL语句实现同步,这种方式叫SQL Apply。

物理Standby接收完Primary数据库生成的REDO数据后,MRP进程以介质恢复的方式实现同步,这种方式也叫Redo Apply。 

  1. 使用LGWR 进程的SYNC 方式

1)Primary Database 产生的Redo日志要同时写到日志文件和网络。也就是说LGWR进程把日志写到本地日志文件的同时还要发送给本地的LNSn进程(Network Server Process),再由LNSn(LGWR Network Server process)进程把日志通过网络发送给远程的目的地,每个远程目的地对应一个LNS进程,多个LNS进程能够并行工作。

2)LGWR 必须等待写入本地日志文件操作和通过LNSn进程的网络传送都成功,Primary Database上的事务才能提交,这也是SYNC的含义所在。

3)Standby Database的RFS进程把接收到的日志写入到Standby Redo Log日志中。

4) Primary Database的日志切换也会触发Standby Database 上的日志切换,即Standby Database 对Standby Redo Log的归档,然后触发Standby Database 的MRP或者LSP进程恢复归档日志。 

  1. 使用LGWR进程的ASYNC 方式

使用LGWR SYNC方法的可能问题在于,如果日志发送给Standby Database过程失败,LGWR进程就会报错。也就是说Primary Database的LGWR 进程依赖于网络状况,有时这种要求可能过于苛刻,这时就可以使用LGWR ASYNC方式。 它的工作机制如下:

1) Primary Database 一旦产生Redo日志后,LGWR 把日志同时提交给日志文件和本地LNS 进程,但是LGWR进程只需成功写入日志文件就可以,不必等待LNSn进程的网络传送成功。

2) LNSn进程异步地把日志内容发送到Standby Database。多个LNSn进程可以并发发送。

3) Primary Database的Online Redo Log 写满后发生Log Switch,触发归档操作,也触发Standby Database对Standby Redo Log 的归档;然后触发MRP或者LSP 进程恢复归档日志。



  1. 进程LNSn:LGWR Network Server process

On the primary database, the LGWR process submits the redo data to one or more network server (LNSn) processes, which then initiate the network I/O in parallel to multiple remote destinations.



DG可以使用ARCH,LGWR来传送日志,但他们都是把日志发送给本地的LNS(如果有多个目标备库,那会启动相应数量的LNS进程,同时发送数据)进程,然后备库那边的RFS进程接收数据,接收到的数据可以存储在备库的备用重做日志文件中或备库的归档日志中,然后再应用到备库中。

主库切换(alter system switch logfile;)可以启动LNS进程, V$MANAGED_STANDBY视图可以查看LNS进程的具体情况:

col group# format a5

set line 9999 pagesize 9999

SELECT a.PROCESS,a.PID,a.STATUS,a.GROUP#,a.SEQUENCE#, a.DELAY_MINS, a.RESETLOG_ID FROM V$MANAGED_STANDBY a;


  1. 如何启动LNS进程?

有3种方法:

  1. alter system switch logfile;
  2. 推荐: 备库启动实时应用后,主库alter system set log_archive_dest_state_2='defer'; alter system switch logfile; alter system set log_archive_dest_state_2='enable'; alter system switch logfile;
  3. 重启备库、主库
    1. LNS进程的后台表现形式

    经过小麦苗的研究,日志传输若采用LGWR进程来传输,则在10g dg中是lns的形式,到了11g变为了nsa和nss的形式了,具体可以参考本文实验部分的总结,不管10还是11g我们都可以用命令ps -ef|grep -v grep|grep -E "ora_lns|ora_nsa|ora_nss"来查询后台进程。





    ---------------------------------------------------------------------------------------------------------------------



    1. 实验部分

    1. 实验目标

    若采用lgwr进程传输日志的话,分别找到10g和11g中,后台进程的表现形式、切换日志时后台的告警日志及V$MANAGED_STANDBY视图展现的内容有何不同。


    1. 实验过程

    以下所有试验过程均在主库操作。

    1. 10g

    实验环境如下:


    1. LGWR SYNC(lgwr 同步)

    -----LGWR SYNC

    alter system set log_archive_dest_2='SERVICE=tns_mydgwl LGWR SYNC db_unique_name=mydgwl valid_for=(ONLINE_LOGFILES,PRIMARY_ROLE)';


    说明LGWR同步方式,后台进程表现为lns,且视图V$MANAGED_STANDBY中表现为LGWR。

    告警日志:

    Sun Jun 14 18:45:58 BEIST 2020

    Thread 1 cannot allocate new log, sequence 31

    Checkpoint not complete

    Current log# 3 seq# 30 mem# 0: /cds/oradata/mydg/redo03.log

    Sun Jun 14 18:46:03 BEIST 2020

    Thread 1 advanced to log sequence 31 (LGWR switch)

    Current log# 1 seq# 31 mem# 0: /cds/oradata/mydg/redo01.log


    1. LGWR ASYNC(lgwr 异步)

    说明LGWR异步方式,后台进程表现为lns,且视图V$MANAGED_STANDBY中表现为LNS。


    告警日志:

    Sun Jun 14 18:45:58 BEIST 2020

    Thread 1 cannot allocate new log, sequence 31

    Checkpoint not complete

    Current log# 3 seq# 30 mem# 0: /cds/oradata/mydg/redo03.log

    Sun Jun 14 18:46:03 BEIST 2020

    Thread 1 advanced to log sequence 31 (LGWR switch)

    Current log# 1 seq# 31 mem# 0: /cds/oradata/mydg/redo01.log



    1. ARCH(归档传输)

    说明arch进程传输日志,后台进程表现为arc,且视图V$MANAGED_STANDBY中表现为ARCH。


    告警日志输出:

    Sun Jun 14 18:15:44 BEIST 2020

    Thread 1 advanced to log sequence 23 (LGWR switch)

    Current log# 2 seq# 23 mem# 0: /cds/oradata/mydg/redo02.log

    Sun Jun 14 18:15:44 BEIST 2020

    Shutting down archive processes

    Sun Jun 14 18:15:49 BEIST 2020

    ARCH shutting down

    ARC4: Archival stopped


    1. 默认传输模式测试


    可以看出10g中,默认情况下为ARCH的同步模式。


    1. 11g

    实验环境如下:

    1. LGWR SYNC(lgwr 同步)


    说明LGWR进程同步传输日志,后台进程表现为nss,且视图V$MANAGED_STANDBY中表现为LGWR,告警日志中表现为LNS: Standby redo logfile selected for thread 1 sequence 98 for destination LOG_ARCHIVE_DEST_2 。


    告警日志:

    Wed Jul 06 13:47:59 2016

    Thread 1 advanced to log sequence 98 (LGWR switch)

    Current log# 3 seq# 98 mem# 0: +DATA/oradesdb/onlinelog/group_3.387.916309939

    Wed Jul 06 13:47:59 2016

    LNS: Standby redo logfile selected for thread 1 sequence 98 for destination LOG_ARCHIVE_DEST_2

    Wed Jul 06 13:47:59 2016

    Archived Log entry 219 added for thread 1 sequence 97 ID 0xffffffff8589c5d0 dest 1:

    Wed Jul 06 13:48:33 2016




    1. LGWR ASYNC(lgwr 异步)

    默认为异步。

    alter system set log_archive_dest_2='SERVICE=oraESKDB LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=oraESKDB' sid='*';

    alter system set log_archive_dest_2='SERVICE=oraESKDB VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=oraESKDB' sid='*';


    告警日志:

    Wed Jul 06 19:24:34 2016

    Thread 1 advanced to log sequence 117 (LGWR switch)

    Current log# 1 seq# 117 mem# 0: +DATA/oradesdb/onlinelog/group_1.258.916309939

    Wed Jul 06 19:24:34 2016

    Archived Log entry 280 added for thread 1 sequence 116 ID 0xffffffff8589c5d0 dest 1:

    Wed Jul 06 19:24:34 2016

    LNS: Standby redo logfile selected for thread 1 sequence 117 for destination LOG_ARCHIVE_DEST_2



    说明LGWR进程异步传输日志,后台进程表现为nsa,且视图V$MANAGED_STANDBY中表现为LNS,告警日志中表现为LNS: Standby redo logfile selected for thread 1 sequence 98 for destination LOG_ARCHIVE_DEST_2 。




    1. ARCH(归档传输)

    在备库查询:


    说明LGWR进程异步传输日志,后台进程表现为nsa,且视图V$MANAGED_STANDBY中表现为LNS,告警日志中表现为LNS: Standby redo logfile selected for thread 1 sequence 98 for destination LOG_ARCHIVE_DEST_2 。

    1. 默认传输模式测试

    可以看出11g下,默认情况为LGWR的异步模式。


    1. 实验总结




    1. 实验中用到的SQL总结

    1. 10g

      col group_# format a5

      col PROCESS format a8

      col CLIENT_PID format a8

      set line 9999 pagesize 9999

      SELECT a.INST_ID,

      a.PROCESS,

      a.client_process,

      a.client_pid,

      a.STATUS,

      a.GROUP# group_#,

      a.thread#,

      a.SEQUENCE#,

      a.DELAY_MINS,

      a.RESETLOG_ID,

      c.SID,

      c.SERIAL#,

      a.PID spid

      FROM gV$MANAGED_STANDBY a, gv$process b, gv$session c

      WHERE a.PID = b.SPID

      and b.ADDR = c.PADDR

      and a.INST_ID = b.INST_ID

      and b.INST_ID = c.INST_ID

      order by a.INST_ID;



      set line 9999

      col DEST_NAME format a20

      col DESTINATION format a15

      col GAP_STATUS format a10

      col DB_UNIQUE_NAME format a15

      col error format a10

      col APPLIED_SCN for 999999999999999

      SELECT al.thread#,

      ads.dest_id,

      ads.DEST_NAME,

      (SELECT ads.TYPE || ' ' || ad.TARGET

      FROM v$archive_dest AD

      WHERE AD.DEST_ID = ADS.DEST_ID) TARGET,

      ADS.DATABASE_MODE,

      ads.STATUS,

      ads.error,

      ads.RECOVERY_MODE,

      ads.DB_UNIQUE_NAME,

      ads.DESTINATION,

      (SELECT MAX(sequence#) FROM v$log na WHERE na.thread# = al.thread#) Current_Seq#,

      MAX(sequence#) Last_Archived,

      max(CASE

      WHEN al.APPLIED = 'YES' AND ads.TYPE <> 'LOCAL' THEN

      al.sequence#

      end) APPLIED_SEQ#

      FROM (SELECT *

      FROM v$archived_log V

      WHERE V.resetlogs_change# =

      (SELECT d.RESETLOGS_CHANGE# FROM v$database d)) al,

      v$archive_dest_status ads

      WHERE al.dest_id(+) = ads.dest_id

      AND ads.STATUS != 'INACTIVE'

      GROUP BY al.thread#,

      ads.dest_id,

      ads.DEST_NAME,

      ads.STATUS,

      ads.error,

      ads.TYPE,

      ADS.DATABASE_MODE,

      ads.RECOVERY_MODE,

      ads.DB_UNIQUE_NAME,

      ads.DESTINATION

      ORDER BY al.thread#, ads.dest_id;



      col name for a100

      set linesize 9999 pagesize 9999

      col NEXT_CHANGE# for 999999999999999

      SELECT THREAD#,

      NAME,

      sequence#,

      archived,

      applied,

      a.NEXT_CHANGE#

      FROM v$archived_log a

      WHERE a.sequence# >= (select max(b.sequence#)-5 from v$log b where b.THREAD#=a.THREAD# )

      AND resetlogs_change# = (SELECT d.RESETLOGS_CHANGE# FROM v$database d)

      ORDER BY a.THREAD#,

      a.sequence#;



      SELECT a.VALUE FROM v$parameter a WHERE a.NAME='log_archive_dest_2';

      SELECT a.PROCESS,a.TRANSMIT_MODE FROM V$ARCHIVE_DEST a WHERE a.DEST_NAME='LOG_ARCHIVE_DEST_2';

      alter system set log_archive_dest_2='SERVICE=tns_mydgwl db_unique_name=mydgwl valid_for=(ONLINE_LOGFILES,PRIMARY_ROLE)' sid='*';

      SELECT a.VALUE FROM v$parameter a WHERE a.NAME='log_archive_dest_2';

      SELECT a.PROCESS,a.TRANSMIT_MODE FROM V$ARCHIVE_DEST a WHERE a.DEST_NAME='LOG_ARCHIVE_DEST_2';





    1. 11g


    col group_# format a5

    col PROCESS format a8

    col CLIENT_PID format a8

    set line 9999 pagesize 9999

    SELECT a.INST_ID,

    a.PROCESS,

    a.client_process,

    a.client_pid,

    a.STATUS,

    a.GROUP# group_#,

    a.thread#,

    a.SEQUENCE#,

    a.DELAY_MINS,

    a.RESETLOG_ID,

    c.SID,

    c.SERIAL#,

    a.PID spid,

    b.PNAME

    FROM gV$MANAGED_STANDBY a, gv$process b, gv$session c

    WHERE a.PID = b.SPID

    and b.ADDR = c.PADDR

    and a.INST_ID = b.INST_ID

    and b.INST_ID = c.INST_ID

    order by a.INST_ID,b.PNAME;



    set line 9999

    col DEST_NAME format a20

    col DESTINATION format a15

    col GAP_STATUS format a10

    col DB_UNIQUE_NAME format a15

    col error format a10

    col APPLIED_SCN for 999999999999999

    SELECT al.thread#,

    ads.dest_id,

    ads.DEST_NAME,

    (SELECT ads.TYPE || ' ' || ad.TARGET

    FROM v$archive_dest AD

    WHERE AD.DEST_ID = ADS.DEST_ID) TARGET,

    ADS.DATABASE_MODE,

    ads.STATUS,

    ads.error,

    ads.RECOVERY_MODE,

    ads.DB_UNIQUE_NAME,

    ads.DESTINATION,

    ads.GAP_STATUS,

    (SELECT MAX(sequence#) FROM v$log na WHERE na.thread# = al.thread#) Current_Seq#,

    MAX(sequence#) Last_Archived,

    max(CASE

    WHEN al.APPLIED = 'YES' AND ads.TYPE <> 'LOCAL' THEN

    al.sequence#

    end) APPLIED_SEQ#,

    (SELECT ad.applied_scn

    FROM v$archive_dest AD

    WHERE AD.DEST_ID = ADS.DEST_ID) applied_scn

    FROM (SELECT *

    FROM v$archived_log V

    WHERE V.resetlogs_change# =

    (SELECT d.RESETLOGS_CHANGE# FROM v$database d)) al,

    v$archive_dest_status ads

    WHERE al.dest_id(+) = ads.dest_id

    AND ads.STATUS != 'INACTIVE'

    GROUP BY al.thread#,

    ads.dest_id,

    ads.DEST_NAME,

    ads.STATUS,

    ads.error,

    ads.TYPE,

    ADS.DATABASE_MODE,

    ads.RECOVERY_MODE,

    ads.DB_UNIQUE_NAME,

    ads.DESTINATION,

    ads.GAP_STATUS

    ORDER BY al.thread#, ads.dest_id;





    ------------物理dg日志应用情况(备库查询为准)

    col name for a100

    set linesize 9999 pagesize 9999

    col NEXT_CHANGE# for 999999999999999

    SELECT THREAD#,

    NAME,

    sequence#,

    archived,

    applied,

    a.NEXT_CHANGE#

    FROM v$archived_log a

    WHERE a.sequence# >= (select max(b.sequence#)-3 from v$log b where b.THREAD#=a.THREAD# )

    AND resetlogs_change# = (SELECT d.RESETLOGS_CHANGE# FROM v$database d)

    ORDER BY a.THREAD#,

    a.sequence#;


    ----物理备库应用进程日志

    --select * from gv$dataguard_status d order by d.inst_id,d.timestamp,d.message_num;

    set line 9999 pagesize 9999

    col message format a85

    SELECT inst_id, severity, FACILITY, TIMESTAMP, MESSAGE

    FROM (select d.inst_id,

    FACILITY,

    SEVERITY,

    TIMESTAMP,

    MESSAGE,

    rank() over(partition by d.inst_id ORDER BY d.message_num desc) rank_order

    from gv$dataguard_status d)

    where rank_order <= 5

    order by inst_id, rank_order desc;



    ---是否启用实时应用

    ps -ef|grep ora_mrp

    --通用:select RECOVERY_MODE from v$archive_dest_status;


    alter database recover managed standby database using current logfile disconnect from session;

    alter database recover managed standby database cancel;


    select thread#,low_sequence#,high_sequence# from v$archive_gap;



    SELECT a.VALUE FROM v$parameter a WHERE a.NAME='log_archive_dest_2';

    SELECT a.PROCESS,a.TRANSMIT_MODE FROM V$ARCHIVE_DEST a WHERE a.DEST_NAME='LOG_ARCHIVE_DEST_2';

    alter system set log_archive_dest_2='SERVICE=tns_mydgwl db_unique_name=mydgwl valid_for=(ONLINE_LOGFILES,PRIMARY_ROLE)' sid='*';

    SELECT a.VALUE FROM v$parameter a WHERE a.NAME='log_archive_dest_2';

    SELECT a.PROCESS,a.TRANSMIT_MODE FROM V$ARCHIVE_DEST a WHERE a.DEST_NAME='LOG_ARCHIVE_DEST_2';


    ---------------------------------------------------------------------------------------------------------------------





    About Me

    ..........................................................................................................................................................................................................

    本文作者:小麦苗,只专注于数据库的技术,更注重技术的运用

    本文在ITpub(http://blog.itpub.net/26736162)和博客园(http://www.cnblogs.com/lhrbest)有同步更新

    本文地址:http://blog.itpub.net/26736162/viewspace-2121688/

    本文pdf版:http://yunpan.cn/cdEQedhCs2kFz (提取码:ed9b) 

    小麦苗分享的其它资料:http://blog.itpub.net/26736162/viewspace-1624453/

    联系我请加QQ好友(642808185),注明添加缘由

    于 2016-07-06 10:00~ 2016-07-07 19:00 在中行完成

    【版权所有,文章允许转载,但须以链接方式注明源地址,否则追究法律责任】

    ..........................................................................................................................................................................................................

    拿起手机扫描下边的图片来关注小麦苗的微信公众号:xiaomaimiaolhr,学习最实用的数据库技术。


     

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26736162/viewspace-2121688/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/26736162/viewspace-2121688/

<think> 我们正在讨论硬件NSS信号的配置,特别是在STM32的CubeMX中如何配置。 用户之前的问题是关于在CubeMX中配置Hardware NSS Signal的方法。 根据引用[1]的提示:在从机配置中,Hardware NSS Signal选择为Hardware NSS Input Signal,并且从机设置为硬件输入比较好。 在CubeMX中配置硬件NSS信号,主要涉及SPI外设的配置。以下是具体步骤: 1. 打开CubeMX,选择相应的STM32微控制器型号。 2. 在Pinout & Configuration界面中,找到需要配置的SPI接口(比如SPI1、SPI2等)。 3. 在SPI的配置界面中,可以看到Mode and Configuration选项,其中有以下关键设置: - Mode: 选择全双工主模式(Full-Duplex Master)或全双工从模式(Full-Duplex Slave)等。 - Hardware NSS Signal: 这个设置项有三种选择: * Disable:禁用硬件NSS,即使用软件控制NSS(通过设置SSM位为1,然后由SSI位控制)。 * NSS Output Signal:用于主机模式。当主机需要控制多个从机时,通常不使用硬件NSS输出(因为硬件NSS输出只能控制一个从机),但在某些情况下,主机可以使用一个NSS输出引脚来控制一个从机。 * NSS Input Signal:用于从机模式。从机通过硬件检测NSS引脚的电平来决定是否被选中。 4. 根据设备是主机还是从机进行配置: - 如果设备作为SPI主机: * 通常,在主机上,我们使用普通的GPIO引脚作为NSS输出(即软件控制),因为主机可能需要多个NSS信号来控制多个从机。但如果主机只控制一个从机,也可以使用硬件NSS输出。 * 若要使用硬件NSS输出,则选择“NSS Output Signal”。此时,硬件NSS引脚(通常是SPI接口的NSS引脚)会被配置为输出,并在数据传输期间自动拉低(选中从机),在传输结束后拉高(取消选中)。 * 配置寄存器:在主机模式下,使能硬件NSS输出需要设置SPI_CR2寄存器的SSOE位(Slave Select Output Enable)为1。 - 如果设备作为SPI从机: * 为了获得更好的可靠性,建议使用硬件NSS输入(如引用[1]所述)。 * 在CubeMX中选择“NSS Input Signal”,这样NSS引脚被配置为输入,从机会检测这个引脚的电平。当NSS为低电平时,从机被选中;当NSS为高电平时,从机忽略总线上的数据。 * 配置寄存器:在从机模式下,需要设置SPI_CR1寄存器的SSM位(Slave Select Management)为0(表示使用硬件NSS)和SSI位(Slave Select Internal)的值被忽略。 5. 引脚配置:在CubeMX的引脚图中,相应的NSS引脚(如PA4、PA15等,具体取决于SPI实例)会被自动分配。在主机模式下选择硬件NSS输出时,该引脚会被配置为复用推挽输出;在从机模式下选择硬件NSS输入时,该引脚会被配置为浮空输入或上拉输入(根据实际电路选择,但CubeMX默认配置通常是浮空输入,用户可能需要根据电路加上拉电阻)。 6. 生成代码:配置完成后,生成初始化代码。在生成的代码中,CubeMX会配置SPI的相应寄存器,包括使能硬件NSS功能。 注意:在主机模式下使用硬件NSS输出时,主机只能控制一个从机(因为只有一个NSS输出引脚)。如果需要控制多个从机,则必须使用软件NSS(即用多个GPIO模拟NSS信号)并禁用硬件NSS。 下面是一个配置示例(以SPI1为例): - 主机配置(只控制一个从机): * Mode: Full-Duplex Master * Hardware NSS Signal: NSS Output Signal * 其他参数(如波特率预设、时钟极性相位等)按需设置。 - 从机配置: * Mode: Full-Duplex Slave * Hardware NSS Signal: NSS Input Signal * 其他参数必须与主机一致(如时钟极性相位、数据大小等)。 生成代码后,在主机初始化代码中,我们可以看到类似这样的设置(以HAL库为例): hspi1.Instance = SPI1; hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT; // 硬件NSS输出 ... // 其他参数 HAL_SPI_Init(&hspi1); 在从机初始化代码中: hspi1.Instance = SPI1; hspi1.Init.NSS = SPI_NSS_HARD_INPUT; // 硬件NSS输入 ... // 其他参数 HAL_SPI_Init(&hspi1); 这样,硬件NSS信号就被配置好了。 注意事项:硬件NSS信号的电平变化必须符合SPI时序要求,即在数据传输开始前NSS拉低,结束后拉高。使用硬件NSS可以确保这一时序由硬件自动控制,从而避免软件延迟带来的问题。 相关问题: 1. 在CubeMX中配置硬件NSS输出时,如何控制多个从机? 2. 使用硬件NSS输入时,从机如何避免总线冲突? 3. 硬件NSS信号在通信异常情况下如何恢复? </think> ### CubeMX中硬件NSS信号配置方法 在STM32CubeMX中配置硬件NSS信号需要根据设备角色(主机/从机)进行不同设置,以下是详细步骤和关键配置项: #### **1. 主机模式配置** 当设备作为**SPI主机**时: 1. 在SPI配置界面选择 **Mode → Full-Duplex Master** 2. **Parameter Settings → Hardware NSS Signal → NSS Output Signal** (使能主机主动输出NSS信号) 3. 关键寄存器配置: - 设置 `SSOE=1` (Slave Select Output Enable) - 自动配置NSS引脚为复用推挽输出 ```c // 生成的HAL库配置代码示例 hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT; HAL_SPI_Init(&hspi1); ``` **物理行为**:数据传输时自动拉低NSS引脚电平,传输结束自动拉高[^1]。 #### **2. 从机模式配置** 当设备作为**SPI从机**时: 1. 在SPI配置界面选择 **Mode → Full-Duplex Slave** 2. **Parameter Settings → Hardware NSS Signal → NSS Input Signal** (配置从机检测外部NSS信号) 3. 关键寄存器配置: - 设置 `SSM=0` (禁用软件NSS管理) - 自动配置NSS引脚为浮空输入 ```c // 生成的HAL库配置代码示例 hspi2.Init.NSS = SPI_NSS_HARD_INPUT; HAL_SPI_Init(&hspi2); ``` **物理行为**:仅当检测到NSS引脚低电平时响应主机指令[^1]。 #### **3. 关键配置注意事项** - **引脚映射**: NSS引脚固定对应SPI接口的`PA4`(SPI1)/`PA15`(SPI2),CubeMX自动锁定(黄色锁形图标) - **时序同步**: NSS信号变化必须与SCK时钟相位对齐,建议配置: - `Clock Polarity (CPOL) → Low` - `Clock Phase (CPHA) → 1 Edge` - **多从机系统**: 主机需禁用硬件NSS改用软件NSS(通过GPIO模拟多个片选信号) > **配置验证建议**: > 使用CubeMX的"Clock Configuration"确保SPI时钟不超过从设备最大频率,并通过"Project Manager → Generate Code"后检查`MX_SPIx_Init()`函数中的NSS配置参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值