版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Z-STACK之cc2530 串口驱动详解上Z-STACK 中串口采用 DMA 和 ISR 两种方式,本章主要讲解 ISR 方式的串口驱动。在 OASL 操作系统轮询时调用了 Hal_ProsPoll ()函数,在此函数中如果定义了 HAL_UART=TRUE,则轮询串口,看时候有数据要发送或有数据要接收。定位到HalUARTPoll()函数中,如果是采用ISR 方式即HAL_UART_ISR为 1 或 2 时,调用 ISR 串口轮询函数 HalUARTPollISR(),在这个函数中调用了串口的回调函数,这个过程等会儿讲。先来看看头文件 hal_uart.h,此头文件中定义了 typedef
2、 void (*halUARTCBack_t) (u8 port,u8 event);串口回调函数的函数指针,定义了串口缓冲区 halUARTBufControl_t 结构体以及针对串口配置的结构体 halUARTCfg_lUARTIoctl_t 结构体没用到不用管。其中还有相关的宏定义,这个根据 datasheet 看。接下来看_hal_uart_isr.c 文件。HAL_UART_ISR_RX_AVAIL()这个宏定义是返回接收缓冲区中可接收数据的长度大小,HAL_UART_ISR_TX_AVAIL()这个宏定义返回发送缓冲区中空位置的长度大小。下面看看这个结构体typedef struc
3、tu8 rxBufHAL_UART_ISR_RX_MAX;#if HAL_UART_ISR_RX_MAX 256u8 rxHead;volatile u8 rxTail;#elseu16 rxHead;volatile u16 rxTail;#endifu8 rxTick;u8 rxShdw;u8 txBufHAL_UART_ISR_TX_MAX;#if HAL_UART_ISR_TX_MAX callBackFunc;/ Only supporting subset of baudrate for code size - other issible.HAL_UART_ASSERT(confi
4、g-baudRate = HAL_UART_BR_9600) |(config-baudRate = HAL_UART_BR_19200) |(config-baudRate = HAL_UART_BR_38400) |(config-baudRate = HAL_UART_BR_57600) |(config-baudRate = HAL_UART_BR_115200);if (config-baudRate = HAL_UART_BR_57600 |config-baudRate = HAL_UART_BR_115200)UxBAUD = 216;elseUxBAUD = 59;switc
5、h (config-baudRate)case HAL_UART_BR_9600:UxGCR = 8;break;case HAL_UART_BR_19200:UxGCR = 9;break;case HAL_UART_BR_38400:case HAL_UART_BR_57600:UxGCR = 10;break;default:UxGCR = 11;break;/ 8 bits/char; no parity; 1 stit; stit hi.if (config-flowControl)UxUCR = UCR_FLOW | UCR_STOP;PxSEL |= HAL_UART_Px_RT
6、S | HAL_UART_Px_CTS;elseUxUCR = UCR_STOP;UxCSR |= CSR_RE;URXxIE = 1;UxDBUF = 0; / Prime the ISR pump.将回调函数赋值给 isrCfg 的 uartCB 成员,然后根据设置的不同波特率对 UxBAUD 和 UxGCR 作相应的设置,最后使能串口接收以及打开串口接收中断,将 UxDBUF 清零。看下串口读数据函数sic u16 HalUARTReadISR(u8 *buf, u16 len)u16 cnt = 0;while (isrCfg.rxHead != isrCfg.rxTail) & (c
7、nt = HAL_UART_ISR_RX_MAX)isrCfg.rxHead = 0;cnt+;return cnt;这个函数和串口写数据函数 HalUARTWriteISR 是在回调函数中被调用,由用户自定义操作。此函数只是将接收缓冲区中的数据赋值给 buf 然后相应 rxHead 增加 len 个长度,返回读的数据长度。这个函数要对照串口接收终端函数理解#if (HAL_UART_ISR = 1)HAL_ISR_FUNCTION( halUart0RxIsr, URX0_VECTOR )#elseHAL_ISR_FUNCTION( halUart1RxIsr, URX1_VECTOR )#
8、endifu8 tmp = UxDBUF;isrCfg.rxBufisrCfg.rxTail = tmp;/ Re-sync the shadow on any 1st byte received.if (isrCfg.rxHead = isrCfg.rxTail)isrCfg.rxShdw = ST0;if (+isrCfg.rxTail = HAL_UART_ISR_RX_MAX)isrCfg.rxTail = 0;isrCfg.rxTick = HAL_UART_ISR_IDLE;在接收中断函数中,将接收到的一字节数据填入 rxBuf 中,注意在接收数据时是将数据填入 rxBuf,然后将
9、 rxTail 加 1,即在缓冲区读数据时是在缓冲区首位置开始读,在串口接收数据时是将数据放在 rxTail即缓冲区末位置。看最后一句代码,将 HAL_UART_ISR_IDLE 即 198 赋值给 rxTick,这个值为系统轮询串口时是否需要操作串口的等待时间,其实可以计算一下,采用的是 32.768kHz 的外部时钟,用 198除以 32.768 约等于 6ms,即每次等待时间为 6ms,如果每次系统经过轮询之后检查 6ms 是否用完,是则调用回调函数。if (isrCfg.rxHead = isrCfg.rxTail)isrCfg.rxShdw = ST0;这句代码的意思是当缓冲区清空的
10、时候,即接收的数据全部被读出来了之后,重新将 rxShdw 赋值 ST0,以计算下一次轮询串口需要数据的时间。接下来看串口写数据函数sic u16 HalUARTWriteISR(u8 *buf, u16 len)u16 cnt;/ Accept all-or-none on write request.if (HAL_UART_ISR_TX_AVAIL() len)return 0;for (cnt = 0; cnt = HAL_UART_ISR_TX_MAX-1)isrCfg.txTail = 0;elseisrCfg.txTail+;/ Keep re-enabling Iit migh
11、t be keng up with this loop due to others.IEN2 |= UTXxIE;return cnt;先检查发送缓冲区是否有可写的 len 长度的位置。然后将 buf 里面的数据给 txBuf,同时将 txTail增加,这正好跟 read 相反,即往缓冲区里面填充数据是在末尾填充,当发送的时候是在发送缓冲区里面取数据,即在缓冲区开头取数据。每次填充一个数据时就开一次发送中断,这样时数据及时发送出去。看下串口发送中断函数#if (HAL_UART_ISR = 1)HAL_ISR_FUNCTION( halUart0TxIsr, UTX0_VECTOR )#els
12、eHAL_ISR_FUNCTION( halUart1TxIsr, UTX1_VECTOR )#endifif (isrCfg.txHead = isrCfg.txTail)IEN2 &= UTXxIE;isrCfg.txMT = 1;elseUTXxIF = 0;UxDBUF = isrCfg.txBufisrCfg.txHead+;if (isrCfg.txHead = HAL_UART_ISR_TX_MAX)isrCfg.txHead = 0;当发送缓冲区中没有数据要发送的时候,即 txHead 等于 txTail,此时将发送中断,将 txMT 标志位置 1,表示发送缓冲区为空,否则(有
13、数据要发送)将串口发送中断标志清零,然后往 UxDBUF 写数据。最后很重要的一个函数即串口轮询函数sic void HalUARTPollISR(void)if (isrCfg.uartCB != NULL)u16 cnt = HAL_UART_ISR_RX_AVAIL();u8 evt = 0;if (isrCfg.rxTick)/ Use the LSB of the sleep timer (ST0 must be readanyway).u8 decr = ST0 - isrCfg.rxShdw;if (isrCfg.rxTick decr)isrCfg.rxTick -= decr
14、;elseisrCfg.rxTick = 0;isrCfg.rxShdw = ST0;if (cnt = HAL_UART_ISR_RX_MAX-1)evt = HAL_UART_RX_FULL;else if (cnt = HAL_UART_ISR_HIGH)evt = HAL_UART_RX_ABOUT_FULL;else if (cnt & !isrCfg.rxTick)evt = HAL_UART_RX_TIMEOUT;if (isrCfg.txMT)isrCfg.txMT = 0;evt |= HAL_UART_TX_EMPTY;if (evt)isrCfg.uartCB(HAL_U
15、ART_ISR-1, evt);这个函数在上面说了是在系统每次循环的时候被调用。如果 rxTick 不为 0,则u8 decr = ST0 - isrCfg.rxShdw;if (isrCfg.rxTick decr)isrCfg.rxTick -= decr;elseisrCfg.rxTick = 0;ST0 表示睡眠定时器当前的计数值,而 rxShdw的是上次串口接收时候的计数值,这样 decr 就表示轮询了一次之后经过的时间,如果此时间比 rxTick 大就将 rxTick 清零,表示时间到了需要接收数据,否则就将 rxTick 值减去 decr,还要继续等待 rxTick-decr 这
16、么长时间。接下来 isrCfg.rxShdw=ST0;当前的睡眠定时器的值以便下一次轮询时候的比较。接下来便是串口事件if (cnt & !isrCfg.rxTick)evt = HAL_UART_RX_TIMEOUT;看这行代码,当 cnt 不为 0 且 rxTick 为 0 的时候则标志串口接收超件,最后if (evt)isrCfg.uartCB(HAL_UART_ISR-1, evt);如果有串口事件则调用回调函数,对缓冲区中的数据进行处理。以上便是 Z-STCAK 中串口驱动的 ISR 方式,如果有理解的地方还希望指示。串口在 ZigBee协议解决方案的开发过程中有很重要的作用。如果能
17、这个串口的工作原理,那么开发调试起来就会得心应手。Z-STACK之cc2530 串口驱动详解下式 DMA,实际上 Z-STACK 中就是采用的这种方式,看 hal_board_cfg.h本文介绍串口驱动的另文件中如下代码#if HAL_UART/ Always prefer to use DMA over ISR.#if HAL_DMA#ifndef HAL_UART_DMA#if (defined ZAPP_P1) | (defined ZTOOL_P1)#define HAL_UART_DMA 1#elif (defined ZAPP_P2) | (defined ZTOOL_P2)#de
18、fine HAL_UART_DMA 2#else#define HAL_UART_DMA 1#endif#endif#define HAL_UART_ISR 0#else#ifndef HAL_UART_ISR#if (defined ZAPP_P1) | (defined ZTOOL_P1)#define HAL_UART_ISR 1#elif (defined ZAPP_P2) | (defined ZTOOL_P2)#define HAL_UART_ISR 2#else#define HAL_UART_ISR 1#endif#endif#define HAL_UART_DMA 0#end
19、if/ Used to set P2 priority - USART0 over USART1 if bore defined.#if (HAL_UART_DMA = 1) | (HAL_UART_ISR = 1)#define HAL_UART_PRIPO0 x00#else#define HAL_UART_PRIPO0 x40#endif#else#define HAL_UART_DMA 0#define HAL_UART_ISR 0#endif可以看出 z-stack 中串口驱动使用的是 DMA 方式。上篇文章讲了 DMA 具体工作方式及原理,这里就说说串口是如何使用 DMA 的。先看
20、驱动源文件_hal_uart_dma.c先看一下串口 DMA 方式中很重要的一个结构体 uartDMACfg_ttypedef structu16 rxBufHAL_UART_DMA_RX_MAX;#if HAL_UART_DMA_RX_MAX 256u8 rxHead;u8 rxTail;#elseu16 rxHead;u16 rxTail;#endifu8 rxTick;u8 rxShdw;u8 txBuf2HAL_UART_DMA_TX_MAX;#if HAL_UART_DMA_TX_MAX callBackFunc;/ Only supporting subset of baudrat
21、e for code size - other issible.HAL_UART_ASSERT(config-baudRate = HAL_UART_BR_9600) |(config-baudRate = HAL_UART_BR_19200) |(config-baudRate = HAL_UART_BR_38400) |(config-baudRate = HAL_UART_BR_57600) |(config-baudRate = HAL_UART_BR_115200);if (config-baudRate = HAL_UART_BR_57600 |config-baudRate =
22、HAL_UART_BR_115200)UxBAUD = 216;elseUxBAUD = 59;switch (config-baudRate)case HAL_UART_BR_9600:UxGCR = 8;dmaCfg.txTick = 35; / (32768Hz / (9600bps / 10 bits)/ 10 bits include start and stits.break;case HAL_UART_BR_19200:UxGCR = 9;dmaCfg.txTick = 18;break;case HAL_UART_BR_38400:UxGCR = 10;dmaCfg.txTic
23、k = 9;break;case HAL_UART_BR_57600:UxGCR = 10;dmaCfg.txTick = 6;break;default:/ HAL_UART_BR_115200UxGCR = 11;dmaCfg.txTick = 3;break;/ 8 bits/char; no parity; 1 stit; stit hi.if (config-flowControl)UxUCR = UCR_FLOW | UCR_STOP;PxSEL |= HAL_UART_Px_CTS;/ DMA Rx is always on (self-resetting). So flow m
24、ust be controlled by the S/W polling theRx/ buffer level. Start by allowing flow.PxOUT &= HAL_UART_Px_RTS;PxDIR |= HAL_UART_Px_RTS;elseUxUCR = UCR_STOP;dmaCfg.rxBuf0 = *(volatile u8 *)DMA_UDBUF;/ Clear the DMA Rx trigger.HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_RX);HAL_DMA_ARM_CH(HAL_DMA_CH_RX);osal_memset(dmaC
25、fg.rxBuf, (DMA_PAD 0 xFF), HAL_UART_DMA_RX_MAX*2);UxCSR |= CSR_RE;UxDBUF = 0; / Prime the DMA-ISR pump./ Initializet TX DMA is not pendingdmaCfg.txDMnding = FALSE;dmaCfg.txShdwValid = FALSE;首先根据配置设定 UART 的波特率及 txTick,如果采用流控制,则要设置 UxUCR、PxSEL、PxOUT、PxDIR。一般都没有采用硬件流控制。dmaCfg.rxBuf0 = *(volatile u8 *)D
26、MA_UDBUF;这行代码uart 的缓冲寄存器,其作用是清除Rx 的 DMA 触发。然后启动 Rx 的 DMA 传输,注意到初始化函数中有这段注释:/* The trick is to cfg DMA to xfer 2 bytes for every 1 byte of Rx.* The byte after the Rx Data Buffer is the Baud Cfg Register,* which always has a known value. So init Rx buffer to inverse oft* known value. DMA word xfer wil
27、l flip the bytes, so every valid Rx byte*he Rx buffer will be preceded by a DMA_PAD char equal to the* Baud Cfg Register value.*/所以将 DMA_PAD 0 xFF 填充整个 rxBuf,即 osal_memset(dmaCfg.rxBuf, (DMA_PAD 0 xFF),HAL_UART_DMA_RX_MAX*2);接着使能串口接收,将 UxDBUF 置 0,Prime the DMA-ISR pump,这一句不知体作用是什么。最后将 dmaCfg 的 txDMn
28、ding 和 txShdwValid 置为 FALSE。看看 HalUARTReadDMA 这个函数,它从 UART 中一些数据到 Buf 中,sic u16 HalUARTReadDMA(u8 *buf, u16 len)u16 cnt;for (cnt = 0; cnt = HAL_UART_DMA_RX_MAX)dmaCfg.rxHead = 0;PxOUT &= HAL_UART_Px_RTS; / Re-enable the flow on any read.return cnt;这个函数里面主要理解几个宏定义数据的时候是从 rxHead 位置开始,每读一个数据 rxHead就加 1
29、。串口在每次接收到一个数据时,是将其放在 rxBuf 每个 16 位字的前八位,后八位为 DMA_PAD,所以当该数据的高八位等于 DMA_PAD 时表明 rxBuf 中有数据了。#defineHAL_UART_DMA_NEW_RX_BYTE(IDX)(DMA_PAD=HI_U16(dmaCfg.rxBuf(IDX)根据 Rx 的 DMA 配置知道,串口每次接收一个数据完成时便触发 DMA 传输,此时将 U0DBUF 中的 8位数据传送到 rxBuf 中,rxBuf 中的数据位置是逐字增加的,假如串口接收到 10 个数据,则 rxBuf 中前 10 个位置便是这 10个数据,只是每个数据后面有
30、填充位为 DMA_PAD 。这里有一个不明白的地方:在初始化的时候 rxBuf中填充的是 DMA_PAD0 xFF,为什么将 HI_U16(dmaCfg.rxBuf(IDX)与 DMA_PAD 比较,且两者相同时就说明 rxBuf 中有数据了。然后就是每次串口接收数据将其发送到 rxBuf 中某个内存的低地址还是高地址,this is a problem!从宏定义上来看,串口中的数据和 DMA_PAD0 xFF 的值组成 16 位数,且串口中的数据位低八位,DMA_PAD0 xFF 为高八位。在数据后面加一个 PAD 位作用呢?Thinking.以上问题等想通了再l you。Come back
31、!HalUARTReadDMA 函数返回到数据的长度。接下来看看这个函数 HalUARTWriteDMA,其功能是将 buf 中的数据写进 txBuf,写的数据长度为lensic u16 HalUARTWriteDMA(u8 *buf, u16 len)u16 cnt;halSe_t his;u8 txIdx, txSel;/ Enforce all or none.if (len + dmaCfg.txIdxdmaCfg.txSel) HAL_UART_DMA_TX_MAX)return 0;HAL_ENTER_CRITICAL_SECTION(his);txSel = dmaCfg.txS
32、el;txIdx = dmaCfg.txIdxtxSel;HAL_EXIT_CRITICAL_SECTION(his);for (cnt = 0; cnt len; cnt+)dmaCfg.txBuftxSeltxIdx+ = bufcnt;HAL_ENTER_CRITICAL_SECTION(his);if (txSel != dmaCfg.txSel)HAL_EXIT_CRITICAL_SECTION(his);txSel = dmaCfg.txSel;txIdx = dmaCfg.txIdxtxSel;for (cnt = 0; cnt HAL_UART_DMA_TX_MAX) retu
33、rn 0; 如果要写入的数据加上 rxBuf 中的数据长度大于 HAL_UART_DMA_TX_MAX,则直接返回 0,此时不能写入数据txSel = dmaCfg.txSel;txIdx = dmaCfg.txIdxtxSel;局部变量 txSel 和 txIdx 分别暂存 dmaCfg 中的 txSel 和 txIdx。for (cnt = 0; cnt decr)dmaCfg.rxTick -= decr;dmaCfg.rxShdw = ST0;elsedmaCfg.rxTick = 0;cnt = HalUARTRxAvailDMA();elsedmaCfg.rxTick = 0;if
34、 (cnt = HAL_UART_DMA_FULL)evt = HAL_UART_RX_FULL;else if (cnt = HAL_UART_DMA_HIGH)evt = HAL_UART_RX_ABOUT_FULL;PxOUT |= HAL_UART_Px_RTS;else if (cnt & !dmaCfg.rxTick)evt = HAL_UART_RX_TIMEOUT;if (dmaCfg.txMT)dmaCfg.txMT = FALSE;evt |= HAL_UART_TX_EMPTY;if (dmaCfg.txShdwValid)u8 decr = ST0;decr -= dm
35、aCfg.txShdw;if (decr dmaCfg.txTick)/ No protection for txShdwValid is required/ because while the shadow was valid, DMA ISR cannot be triggered/ to cause concurrent acs to this variable.dmaCfg.txShdwValid = FALSE;if (dmaCfg.txDMnding & !dmaCfg.txShdwValid)/ UART TX DMA is expected to be fired and en
36、ough time has lapsed since last DMA ISR/ to knowt DBUF can be overwrittenhalDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_DMA_CH_TX);halSe_tSe;/ Clear the DMnding flagdmaCfg.txDMnding = FALSE;HAL_DMA_SET_SOURCE(ch, dmaCfg.txBufdmaCfg.txSel);HAL_DMA_SET_LEN(ch, dmaCfg.txIdxdmaCfg.txSel);dmaCfg.txSel = 1;H
37、AL_ENTER_CRITICAL_SECTION(Se);HAL_DMA_ARM_CH(HAL_DMA_CH_TX);doasm(NOP); while (!HAL_DMA_CH_ARMED(HAL_DMA_CH_TX);HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_TX);HAL_DMA_MAN_TRIGGER(HAL_DMA_CH_TX);HAL_EXIT_CRITICAL_SECTION(Se);if (evt & (dmaCfg.uartCB != NULL)dmaCfg.uartCB(HAL_UART_DMA-1, evt);这个 poll 函数即轮询发送缓冲区也轮询接
38、收缓冲区。第一个 if 语句里面判断接收缓冲区中是否有数据,如果有则 tail = findTail(),找到缓冲区数据的末位置,如果 dmaCfg.rxTail != tail,则还有数据要传输,分别设置 dmaCfg.rxShdw 和 dmaCfg.rxTick,这两个成员跟串口驱动 ISR 方式中 isrCfg 的这两个成员意义相同,这里不再赘余。如果没有数据需要接收了,则判断 dmaCfg.rxTick 是否为 0,如果不为 0,则将其置为减去上次轮询的时候到本次程序跑的时间的值,decr 为程序跑的时间,如果 rxTick 大于decr,则说明还没有到进行数据传输的时间,如果小于则时
39、间到了将 rxTick 置为 0,在下一次轮询的时候,则可以调用回调函数接收缓冲区的数据了。该代码块最后调用HalUARTRxAvailDMA()计算出接收缓冲区的有效数据的长度。如果 HAL_UART_DMA_NEW_RX_BYTE 判断的结果是缓冲区没有数据,则仅将 txTick 置为 0。第二个 if 语句若 cnt = HAL_UART_DMA_FULL,则置串口事件 HAL_UART_RX_FULL 表示缓冲区已满。接下来如果 cnt 不等于 0,且 dmaCfg.rxTick 为 0,则置串口事件 HAL_UART_RX_TIMEOUT 表示到了缓冲区数据的事件,赶紧调用串口回调函
40、数吧!if (dmaCfg.txMT)dmaCfg.txMT = FALSE;evt |= HAL_UART_TX_EMPTY;txMT 标志发送缓冲区是否为空,为 TRUE 为空,置为 HAL_UART_TX_EMPTY 事件。接下来两个 if 语句。if (dmaCfg.txShdwValid)u8 decr = ST0;decr -= dmaCfg.txShdw;if (decr dmaCfg.txTick)/ No protection for txShdwValid is required/ because while the shadow was valid, DMA ISR ca
41、nnot be triggered/ to cause concurrent acs to this variable.dmaCfg.txShdwValid = FALSE;txShdValid 这个成员变量是对发送缓冲区有效的,即如果为 true,则发送数据只有经过 txTick 时间之后才能进行数据传输,否则则说明 txTick 时间已到,这个 txTick 是串口初始化的时候就已经确定的,是个定值,跟 rxTick 不一样。所以就定义了 txShdwValid 这个成员变量。第二个 if 语句就先判断 txDMnding 和 txShdwValid,如果前者为 TRUE,后者为 FALS
42、E,则 UARTTX DMA is expected to be fired and enough time has lapsed since last DMA ISR to knowtDBUF can be overwritten;真正发送数据到 UxDBUF 中 是在这里面进行的!因为这里重新配置了 TX的 DMA 配置描述符,有一句代码 HAL_DMA_MAN_TRIGGER(HAL_DMA_CH_TX);手动开启 DMA 传输,则数据直接从 dmaCfg.txBufdmaCfg.txSel传输到 UxDBUF 中,dmaCfg.txSel=1;这一句代码有一点不解,意思是将 txSel
43、 取为另一个缓冲区,但是这是为何呢!最后一个 if 语句是 evt 不为空且回调函数不为空时,调用串口的回调函数!最后看一下这个 TX 的 DMA 中断程序void HalUARTIsrDMA(void)HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_TX);/ Indicatet the other buffer is free now.dmaCfg.txIdx(dmaCfg.txSel 1) = 0;dmaCfg.txMT = TRUE;/ Set TX shadowdmaCfg.txShdw = ST0;dmaCfg.txShdwValid = TRUE;/ If there is more Tx data ready to go, re-start the DMA immediay o
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年山西电信人员招聘参考题库及答案详解
- 2026年中国石油西藏销售分公司人员招聘笔试参考试题及答案详解
- 2026年临汾市烟草专卖局人员招聘笔试参考试题及答案详解
- 2026年莱芜市烟草专卖局人员招聘考试题库及答案详解
- 2026广西崇左凭祥市商务和口岸管理局招聘1人笔试备考试题及答案解析
- 2026年济南市烟草专卖局人员招聘考试参考试题及答案详解
- 2026年黔西南市烟草专卖局人员招聘考试备考题库及答案详解
- 2026年福建炼化人员招聘笔试参考题库及答案详解
- 2026新疆吐鲁番市维吾尔医医院面向社会招聘编制外聘用人员1人笔试参考题库及答案解析
- 2026年永安财产保险股份有限公司人员招聘考试备考题库及答案详解
- 初中物理八年级下册《摩擦力》教学设计
- 岳阳观盛投资发展有限公司招聘笔试题库2026
- 空调水管道试压冲洗专项方案
- (2026年版)中国有肾脏意义的单克隆免疫球蛋白血症诊治专家共识课件
- 家用电器产品检测合同协议
- 2025年吉林省地理生物会考真题试卷+解析及答案
- 2026年辽宁省铁岭市西丰县第二中学中考二模数学试题(含答案)
- 2026年九省联考化学答案及试卷
- 2026全国高考体育单招考试语文试题试题(含答案)
- 2026年大学生人文知识竞赛题库及答案
- 2025年管理岗面试试题及答案
评论
0/150
提交评论