1. <nobr id="easjo"><address id="easjo"></address></nobr>

      <track id="easjo"><source id="easjo"></source></track>
      1. 
        

      2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
      3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>
          貴州做網站公司
          貴州做網站公司~專業!靠譜!
          10年網站模板開發經驗,熟悉國內外開源網站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等網站程序,可為您提供網站建設,網站克隆,仿站,網頁設計,網站制作,網站推廣優化等服務。我們專注高端營銷型網站,企業官網,集團官網,自適應網站,手機網站,網絡營銷,網站優化,網站服務器環境搭建以及托管運維等。為客戶提供一站式網站解決方案?。?!

          十二.UART串口通訊

          來源:互聯網轉載 時間:2024-01-29 08:06:46

          一個嵌入式設備,串口基本上就是最常用到的外設了,通過串口可以將開發板和電腦連接,也有很多外設是通過串口來進行數據交互的。今天就來搞一下I.MX6UL的串口通訊,實現和電腦通訊的效果。

          UART接口

          I.MX6UL的串口外設叫做UART(Universal Asynchronous Receiver/Trasmitter),即異步串行收發器。UART作為串口的一種,其工作原理也是將數據位一幀一幀的進行傳輸,數據的發送和接收共用一條線纜,所以UART接口與外設相連的時候最少需要3根線:TXD、RXD和GND。下面的圖是UART的通訊格式

          起始位(StartBit)是一個邏輯0

          空閑位:在起始位前面的狀態為邏輯1,表示沒有數據,空閑中。

          數據位:實際要傳輸的數據,一般是按照字節闡述,一個字節8位,低位在前先傳輸,高位在后面傳輸。

          停止位(StopBit)邏輯1,位數可以是1、1.5或2個bit。

          UART電平標準

          UART一般接口電平有TTL和RS232電平,開發板上的TXD和RXD對應的就是TTL電平,使用低電平表示0,高電平表示1;而DB9接口就是對應的RS232接口,用-3~-15V表示邏輯1,+3~+15V表示邏輯0,采用差分線連接。在使用RS232時候一定要注意接口電平,不要燒毀外設。

          由于現在電腦上基本都不帶COM口,而在寫單片機什么的需要串口,這就需要一個USB轉TTL電平的芯片。最常用的就是CH340。比如Arduino(nano版)的的背后就有個CH340C。用過這個芯片和USB連接就可以實現串口功能(很多USB轉232的設備就是用的這個芯片)。

          I.MX6UL的UART接口

          I.MX6UL提供了8組UART接口,結構體如下:

          具備如下特點:

          • 兼容TIA/EIA-232-F標準,最高速率5.0M/s
          • 支持串行IR接口,兼容IrDA,最高速率115200bps
          • 支持9位或多點的RS-485模式
          • 232可以選擇7或8位的字符格式,485模式9bit格式
          • 停止位1或2個bit
          • 可編程的奇偶校驗
          • 最高到115200bit/s自動波特率檢測
          • 等等等等,太多了

          IMX.6UL的UART的功能有非常多,我們這里只用做最基礎的串口通訊功能,具體的實際作用參考手冊Chapter 55給了非常詳細的介紹。

          主要寄存器

          UART相關寄存器也比較多,因為Soc一共有8組UART,這里截取;一組的寄存器映射

          但是要注意的是,雖然8組UART里各個寄存器功能序列是一樣的,但是這個內存映射不是從UART1開始的,而是從UART7開始的。

          下面看看幾個我們要用到的寄存器

          UARTx_URXD

          接收數據寄存器UART Receiver Register,寄存器結構如下:

          寄存器全部為只讀,我們主要用到就是最后的低8位,用來存儲接收的數據。另外,bit[10]=1時可以在RS485模式下,數據結構為9bit時保存第九個bit的數據

          UARTx_UTXD

          發送數據寄存器UART Transmitter Register,用來存放待發送的數據。

          寄存器低8位有效,在7bit數據結構下,bit[7]可以忽略,如果想要將數據寫入該寄存器,需要確認TRDY(UARTx_UCR1[13])必須為高電平,即當前沒有數據被發送。

          UARTx_UCR1

          控制寄存器1(UART Control Register 1)UART提供了4組控制寄存器用來對其進行功能設置,首先是UCR1,先看寄存器結構

          ADEN(bit[15])Automatic Baud Rate Detection Interrupt Enable,自動波特率偵測中斷使能 ,允許ADET標志位(UARTx_USR2 bit[15])觸發中斷

          ADBR(bit[14])Automatic Detection of Baud Rate,自動檢測波特率使能,大概意思就是當該位值為1且ADET被清除時,接收器通過接收一個字符A或者a,對比其ASCII碼為0x41或0x61,去確認合適的比特率。

          TRDYEN(bit[13])Transmitter Ready Interrupt Enable,數據發送準備中斷使能

          IDEN(bit[12])Idle Condition Detected Interrupt Enable,一個什么中斷使能,這個暫時沒搞懂,暫時應該也用不上

          中間幾個中斷使能就不說了,最后一個就是UART的使能UARTEN(bit[0]),整個寄存器我們暫時應該也就是能用到這一個bit。(自動獲取波特率只能到115200,先關閉不用)

          UARTx_UCR2
          控制寄存器2,寄存器結構如下

          手冊上有很詳細的解釋,這里只說一下需要用到的幾個

          IRTS(bit[14])Ignore RTS Pin,1時忽略RTS引腳,我們在使用TTL電平串口信號時只用到RXD和TXD,RTS和CTS一般是不使用的,設置為1即可。

          PREN(bit[8])Parity Enable,校驗使能,1時使能校驗功能

          PROE(bit[7])Parity Odd/Even,校驗方式:1為奇校驗,0為偶校驗

          STPB(bit[6])停止位,0時停止位1bit,1時2bit

          WS(bit[5])Word Size,數據位長度,0時7bit,1時8bit(該長度不包含起始、結束及校驗位)

          TXEN(bit[2])Transmitter Enable,發送數據使能,1時使能

          RXEN(bit[1])Receiver Enable,接收數據使能

          SRET(bit[0])Software Reset,軟件復位,寫0時對FIFO,USR1,USR2,UBIR,UBMR,UBRC,URXD,UTXD和UTS[6:3]進行復位,但復位前保留4個時鐘周期用來進行其他的操作。復位后該位自動置1。

          UARTx_UCR3

          控制寄存器3

          這個我們只用到了一個RXDMUXSEL,因為手冊上說了這個應給被置1

          其他的位我們暫時也都用不到。

          UARTx_UFCR

          緩存控制寄存器UART FIFO Control Register,這里我們主要用來設置分頻器

          RFDIV(bit[9:7])里定義了從CCM過來的時鐘的分頻

          注意這個分頻不是按照數值+1的模式進行分頻的,看具體的值,這個分頻器決定的UART的參考時鐘

          UARTx_USR2

          狀態寄存器1我們也用不到,這里要用到狀態寄存器2

          ADET(bit[15])Automatic Baud Rate Detect Complete,波特率檢測完畢,當1時接收到合適的A或者a字符,需要寫1清除狀態

          TXFE(bit[14])Transmit Buffer FIFO Empty,發送緩存狀態,1時表示緩存區為空

          TXDC(bit[3])Transmitter Complete,發送完成標志位,1時表示發送數據完成,發送寄存器或發送緩存寫入數據,該位自動清零

          RDR(bit[0])Receive Data Ready,數據接收標志位,為1時表示至少還有1個數據要接收

          UARTx_UBIR和UARTx_UBMR

          用來湊波特率的兩個寄存器,參考手冊第55.5章節介紹了波特率的計算方法

          RefFreq就是經過分頻后的參考時鐘,比如我們時鐘為80MHz,分頻為1分頻,想要用115200的波特率,就要自己湊了,正點原子給出的數據是UBMR=3124,UBIR=71,那么

          其實NGP給了個函數,可以根據我們需要的波特率計算出對應的參數。

          UART使用

          使用UART的流程和其他的外設差不多也是先初始化、再使用

          時鐘源設置

          有一點要注意:修改時鐘樹對應的時鐘源,UART和其他的外設用到的不是一個時鐘源,我們前面的用到的都是IPG_CLK,UART用到的的是UART_CLK_ROOT

          我們需要通過CSCDR1選擇6分頻的pll3(480MHz),也就是80MHz,后面分頻器為1分頻。根據手冊可以查出,UART_CLK_SEL為bit[6],值應為1,分頻器UART_CLK_PODR對應bit[5:0],對應2^6+1分頻,1分頻值為0。

          所以要修改我們的clk初始化函數clk_init

          /*--------------------------UART_CLK設置--------------------------*/    /*UART_CLK_ROOT主頻設置為80MHz*/    CCM->CSCDR1 &= ~(1<<6);                //CSCDR1[UART_CLK_SEL](bit[6])=0,時鐘源80MHz    CCM->CSCDR1 &= ~(7<<0);                //CSCDR1[UART_CLK_PODF](bit[5:0])設置為0,對應1分頻/*-------------------------UART_CLK設置完畢------------------------*/

          這步一定要記得!否則波特率就亂了!我在調試的時候就是忘了這一步!

          UART初始化

          UART的初始化包括IO的復用設置、UART參數設置、波特率設置。主要就是設置UCR1、UCR2、UCR3、UFCR、UBIR、UBMR幾個寄存器。在設置寄存器值時,應該按照下面的順序

          • 關閉串口功能(UARTEN=0)
          • 復位UART(SRET=0),復位時等待SRET為1,即復位完畢
          • 設置相關寄存器的值
          • 使能UART

          配置寄存器的過程如下:

              /*配置UART1*/    UART1->UCR1 = 0;    // UART1->UCR1 &= ~(1<<14);    /*配置UCR2*/    UART1->UCR2 = 0;                                 //清除UCR0    UART1->UCR2 |= (1<<1) |(1<<2) |(1<<5)|(1<<14);   //從左起:RXEN=1 TXEN=1 WS=1 IRTS=1                                                     //接收、發送使能、數據長度為8bit 忽略RTS引腳    /*配置UCR3*/    UART1->UCR3 |= (1<<2);                           //RXDMUXSEL=1    //波特率設置115200    UART1->UFCR &= ~(7<<7);                          //RFDIV進行清零    UART1->UFCR = 5<<7;                              //設置1分頻,uart_clk=80MHz    UART1->UBIR = 71;    UART1->UBMR = 3124;

          其實還是比較簡單的。

          其他的幾個關閉、使能等函數放在最后。

          數據接收、發送

          數據的發送、接收就是對URXD、UTXD的低8位進行操作

          /** * @brief           通過UART1發送1個字符 *  * @param c         待發送的字符 */void putc(unsigned char c){    while(((UART1->USR2 >>3) & 0x01) == 0);     //等待前一個發送流程完畢    UART1->UTXD = (c & 0xFF);}/*通過UART1接收一個字符*/unsigned char getc(void){    while(((UART1->USR2)&0x01) == 0);          //等待前一個接收流程完畢    return UART1->URXD;}/** * @brief           發送字符串 *  * @param str       待發送的字符串  */void puts(unsigned *str){    char *p = str;    while(*p){        putc(*p++);    }}

          這樣就完成了所有的功能定義。

          文件結構:

          UART功能的文件結構和其他外設一樣

          兩個文件如下:

          /** * @file bsp_uart.c * @author your name (you@domain.com) * @brief uart功能定義 * @version 0.1 * @date 2022-01-17 *  * @copyright Copyright (c) 2022 *  */#include "bsp_uart.h"http://初始化uart1,波特率固定為115200void uart_init(void){    uart_io_init();             //IO初始化    uart_disable(UART1);        //關閉串口    uart_softreset(UART1);      //復位UART1    /*配置UART1*/    UART1->UCR1 = 0;    // UART1->UCR1 &= ~(1<<14);    /*配置UCR2*/    UART1->UCR2 = 0;                                 //清除UCR0    UART1->UCR2 |= (1<<1) |(1<<2) |(1<<5)|(1<<14);   //從左起:RXEN=1 TXEN=1 WS=1 IRTS=1                                                     //接收、發送使能、數據長度為8bit 忽略RTS引腳    /*配置UCR3*/    UART1->UCR3 |= (1<<2);                           //RXDMUXSEL=1    //波特率設置115200    UART1->UFCR &= ~(7<<7);                          //RFDIV進行清零    UART1->UFCR = 5<<7;                              //設置1分頻,uart_clk=80MHz    UART1->UBIR = 71;    UART1->UBMR = 3124;    uart_enable(UART1);         //使能UART1}/** * @brief IO初始化為UART *  */void uart_io_init(void){       IOMUXC_SetPinMux(IOMUXC_UART1_TX_DATA_UART1_TX,0);//復用為UART1_TX     IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX,0x10b0);    IOMUXC_SetPinMux(IOMUXC_UART1_RX_DATA_UART1_RX,0);    IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX,0x10b0);}/** * @brief           關閉UART串口 *  * @param base      UART結構體 */void uart_disable(UART_Type *base){    base->UCR1 &= (1<<0);}/** * @brief           使能UART串口 *  * @param base      UART結構體 */void uart_enable(UART_Type *base){    base->UCR1 |= (1<<0);}/** * @brief           UART軟復位 *  * @param base      UART結構體 */void uart_softreset(UART_Type *base){    base->UCR2 &= ~(1<<0);                     //SRET=0    while((base->UCR2 & 0x01) == 0 );          //復位完畢,SRET=1}/** * @brief           通過UART1發送1個字符 *  * @param c         待發送的字符 */void putc(unsigned char c){    while(((UART1->USR2 >>3) & 0x01) == 0);     //等待前一個發送流程完畢    UART1->UTXD = (c & 0xFF);}/*通過UART1接收一個字符*/unsigned char getc(void){    while(((UART1->USR2)&0x01) == 0);          //等待前一個接收流程完畢    return UART1->URXD;}/** * @brief           發送字符串 *  * @param str       待發送的字符串  */void puts(unsigned *str){    char *p = str;    while(*p){        putc(*p++);    }}
          bsp_uart.c

          頭文件

          /** * @file bsp_uart.h * @author your name (you@domain.com) * @brief uart頭文件 * @version 0.1 * @date 2022-01-17 *  * @copyright Copyright (c) 2022 *  */#ifndef __BSP_UART_H#define __BSP_UART_H#include "imx6ul.h"void uart_io_init(void);void uart_disable(UART_Type *base);void uart_enable(UART_Type *base);void uart_softreset(UART_Type *base);void putc(unsigned char c);unsigned char getc(void);void puts(unsigned *str);#endif
          bsp_uart.h

          在main函數里導入頭文件以后,調用函數

          int_init();imx6u_clkinit();clk_enable();uart_init();while(1){       puts("input a char");    a=getc();    putc(a);    puts("\r\n");    puts("your input is:");    putc(a);    puts("\r\n");}

          就可以使用串口實現數據交互了。

          PC上運行SecureCRT,使用串口連接,Soc從PC串口接收一個字符,然后返回給PC,就是這么個效果。

          波特率計算

          前面我們已經實現了數據的通訊,但是波特率是固定在115200,并且波特率的計算也是我們湊出來了,可以如果我們需要9600的比特率,還要在湊半天。NXP給我們的SDK包里提供了一個函數,可以直接設置對應的寄存器,這個函數可以直接調用

          /** * @brief                   設置比特率(官方代碼) *  * @param base              UART結構特 * @param baudrate          要設置的比特率 * @param srcclock_hz        */void uart_setbaudrate(UART_Type *base, unsigned int baudrate, unsigned int srcclock_hz){    uint32_t numerator = 0u;        //分子    uint32_t denominator = 0U;        //分母    uint32_t pisor = 0U;    uint32_t refFreqDiv = 0U;    uint32_t pider = 1U;    uint64_t baudDiff = 0U;    uint64_t tempNumerator = 0U;    uint32_t tempDenominator = 0u;    /* get the approximately maximum pisor */    numerator = srcclock_hz;    denominator = baudrate << 4;    pisor = 1;    while (denominator != 0)    {        pisor = denominator;        denominator = numerator % denominator;        numerator = pisor;    }    numerator = srcclock_hz / pisor;    denominator = (baudrate << 4) / pisor;    /* numerator ranges from 1 ~ 7 * 64k */    /* denominator ranges from 1 ~ 64k */    if ((numerator > (UART_UBIR_INC_MASK * 7)) || (denominator > UART_UBIR_INC_MASK))    {        uint32_t m = (numerator - 1) / (UART_UBIR_INC_MASK * 7) + 1;        uint32_t n = (denominator - 1) / UART_UBIR_INC_MASK + 1;        uint32_t max = m > n ? m : n;        numerator /= max;        denominator /= max;        if (0 == numerator)        {            numerator = 1;        }        if (0 == denominator)        {            denominator = 1;        }    }    pider = (numerator - 1) / UART_UBIR_INC_MASK + 1;    switch (pider)    {        case 1:            refFreqDiv = 0x05;            break;        case 2:            refFreqDiv = 0x04;            break;        case 3:            refFreqDiv = 0x03;            break;        case 4:            refFreqDiv = 0x02;            break;        case 5:            refFreqDiv = 0x01;            break;        case 6:            refFreqDiv = 0x00;            break;        case 7:            refFreqDiv = 0x06;            break;        default:            refFreqDiv = 0x05;            break;    }    /* Compare the difference between baudRate_Bps and calculated baud rate.     * Baud Rate = Ref Freq / (16 * (UBMR + 1)/(UBIR+1)).     * baudDiff = (srcClock_Hz/pider)/( 16 * ((numerator / pider)/ denominator).     */    tempNumerator = srcclock_hz;    tempDenominator = (numerator << 4);    pisor = 1;    /* get the approximately maximum pisor */    while (tempDenominator != 0)    {        pisor = tempDenominator;        tempDenominator = tempNumerator % tempDenominator;        tempNumerator = pisor;    }    tempNumerator = srcclock_hz / pisor;    tempDenominator = (numerator << 4) / pisor;    baudDiff = (tempNumerator * denominator) / tempDenominator;    baudDiff = (baudDiff >= baudrate) ? (baudDiff - baudrate) : (baudrate - baudDiff);    if (baudDiff < (baudrate / 100) * 3)    {        base->UFCR &= ~UART_UFCR_RFDIV_MASK;        base->UFCR |= UART_UFCR_RFDIV(refFreqDiv);        base->UBIR = UART_UBIR_INC(denominator - 1); //要先寫UBIR寄存器,然后在寫UBMR寄存器,3592頁         base->UBMR = UART_UBMR_MOD(numerator / pider - 1);    }}

          make的事項

          在導入上面自動設置波特率的函數以后,在make的時候會報錯

          錯誤提示是變量未定義,原因是我們調用uart_setbaudrate這個函數時候需要進行除法運算,而ARM沒有除法運算的硬件結構,進行除法運算需要借助軟件編譯器,軟浮點的實現是在一個叫做libgcc.a的庫中。這個庫需要我們在編譯的時候指定。因為我直接用到樹莓派自帶的交叉編譯器,庫的地址可以在/lib路徑下搜一下:

          教程用的交叉編譯器版本是4.9.4,我用的是8.3

          暫時還沒出現什么問題, 記錄下libgcc.a的路徑,添加在makefile中

           1 CC                := $(CROSS_COMPILE)gcc 2 LD                 := $(CROSS_COMPILE)ld 3 OBJCOPY            := $(CROSS_COMPILE)objcopy  4 OBJDUMP            := $(CROSS_COMPILE)objdump  5  6 LIBPATH            := -lgcc -L /lib/gcc/arm-linux-gnueabihf/8   #制定依賴庫路徑 7  8 $(TARGET).bin : $(OBJS) 9 10     $(LD) -Timx6ul.lds -o $(TARGET).elf $^ $(LIBPATH)         #將所有依賴文件鏈接,生成.elf文件11     $(OBJCOPY) -O binary -S $(TARGET).elf $@                #將elf轉換為依賴的目標集合12     $(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis        #將elf文件反匯編

          要對原先的通用Makefile進行修改:

          • 添加第6行,通過一個變量指定依賴的路徑
          • 修改第4行,在鏈接的時候引用變量

          修改完了make一下,看到會報一個錯!

          原因是我們定義的putc和puts兩個函數和libgcc.a庫里的原生的函數重名了。要解決這個問題還是修改Makefile文件

          1 # 靜態模式 <Targets...>:<tatgets-pattern>:<prereq-patterns...>下面兩天為自寫2 $(SOBJS) :    obj/%.o    :    %.s  #將所有的.s文件編譯成.o文件放在obj文件夾內3     $(CC) -Wall -nostdlib -fno-builtin -c -O2 $(INCLUDE) -o $@ $<4 5 $(COBJS) : obj/%.o : %.c 6     $(CC) -Wall -nostdlib -fno-builtin -c -O2  $(INCLUDE) -o $@ $<

          在第3、6行加上參數-fno-builtin,意思是不調用C語言的內建函數。這樣調用的函數就是我們自己定義的函數了。

          make以后還是有個錯誤

          通過提示大概意思就是要定義一個異常處理的函數raise,對應的ip0我覺得意思是當除數為0時候的異常處理。我們定義一個空函數就可以了。

          void raise(int sig_nr) {}

          在頭文件里聲明,搞定!

          printf格式化函數的移植

          我們前面的串口驅動,只能發送一般的字符,如果需要輸出數字的時候還要將數字轉換為字符,很不方便。一般很常用的方法就是把printf函數映射到串口上,那樣就可以直接使用printf函數來完成格式化輸出了。

          庫移植

          將教程提供的stdio文件夾復制到項目根目錄下,修改Makefile文件

          從文件名稱就可以看出來,目錄下include文件夾里的是頭文件,lib里是源代碼,將該路徑添加到Makefile里。進行make。

          函數調用

          導入這個庫以后就可以直接使用格式化輸入和輸出了

              int a,b;    while(1)    {         printf("請輸入兩個值,用空格隔開");        scanf("%d %d",&a,&b);        printf("\r\n 數據%d+%d=%d\r\n",a,b,a+b);    }

          上面的代碼是在main函數中的,前面初始化串口、時鐘什么的我沒有截取,主要就是看一下怎么使用兩個函數。但是要注意一點:被移植的printf不支持浮點類運算!!!

          這里跟教程有些區別:

          前面說過,正點原子提供的教程上使用的交叉編譯器什4.9.4,而我用到時8.3,我對照在X86架構下使用4.9.4在make的時候會報錯:

          錯誤信息thumb conditional instruction should be in IT block -- `addcs r5,r5,#65536',這個指令集錯誤我沒有找到出處,解決辦法是在編譯C文件時候加上一個參數:Wa,-mimplicit-it=thumb(百度上直接給的方案,沒有找到具體的解決流程和原因)

          修改后的Makefile

          # 靜態模式 <Targets...>:<tatgets-pattern>:<prereq-patterns...>下面兩天為自寫$(SOBJS) :    obj/%.o    :    %.s  #將所有的.s文件編譯成.o文件放在obj文件夾內    $(CC) -Wall -nostdlib -fno-builtin -c -O2 $(INCLUDE) -o $@ $<$(COBJS) : obj/%.o : %.c     $(CC) -Wall -Wa,-mimplicit-it=thumb -nostdlib -fno-builtin -c -O2  $(INCLUDE) -o $@ $<

          燒錄sd卡就行了。

          調試時候的BUG

          在最后調試的時候出現了一個大BUG,這里記錄一下吧,免得以后忘了!

          開始怎么也沒搞清,現象就是添加玩stdio庫以后make能成功,但是用imxdownload下載一直報錯

          先后試過教程提供的源碼,更換了交叉編譯器,重新編譯了下載軟件一直都不行,按理說報dd錯誤是磁盤寫入失敗,燒錄前面的所有程序都可以,在后來發現只要寫入到文件size沒有超過10000Bytes都正常,就沒想過是卡的問題。直到發現燒錄完以前的程序發現上電后初始化非常慢,想到卡可能出問題了,用fdisk格式化失敗,Ubuntu下使用好幾個磁盤工具格式化都報錯,換了個讀卡器也不行。沒辦法找了個win10的PC,格式化了一下,還是不行,用Imager燒錄了個樹莓派的鏡像,沒問題,回來重新燒錄一遍,竟然好了!估計是最近經常用讀卡器是不是有什么問題了。

          標簽:uart串口-

          網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...

          在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...

          在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...

          騰訊QQ如何下載?在軟件商店或是到官網就可以下載,在桌面建一個快捷就可以了。1、再打開網絡瀏覽器,在搜索引擎內然后輸入(直接下載)點擊搜索。2、你選一個網站點擊(立即上網下載)。3、在等待去下載結束后直接點擊(運行)。4、點擊(立即完全安裝)耐心的等待安裝完成即可建議使用電腦軟件啦。拓展:手機和電腦互傳文件,首先前提是要不滿足看看兩個條件:1.手機安卓版本一般不低于4.12,電腦前提是為或以上。2...

          手機撥號上網是什么意思?撥號設置是設置默認使用哪張手機卡打電話,上網是開通數據,使用默認使用手機卡的流量。手機如何撥號上網?先打開撥號選項;點擊手機的撥號盤,點擊右下角三個點的設置選項;點擊【設置】,部分手機點擊【更多】選項按鈕顯示【設置】;可以看到,除了1是語音郵件設置,還可以設置2到9的快速撥號鍵。點擊添加聯系人,根據自己的實際情況在通訊錄中選擇經常聯系的聯系人。按照彈出的提示一步一步操作。1...

          淘寶的特價是怎樣設置出來的?1、先打開淘寶首頁,直接點擊右上角“賣家中心”,輸入賬號密碼,剛剛進入商家后臺;2、左側找到“店鋪營銷工具”,點擊進入,找不到“單品寶”,再點擊進入;3、再點擊“剛建活動”;4、按步驟如何填寫活動名稱、活動時間等(注:活動時間最長可設置中180天),如需折扣商品只有那一個價格即選擇“商品級”,如有多個完全不同價格即選擇類型“SKU級”;5、選擇類型要折扣的活動商品,直接...

          TOP
          国产初高中生视频在线观看|亚洲一区中文|久久亚洲欧美国产精品|黄色网站入口免费进人
          1. <nobr id="easjo"><address id="easjo"></address></nobr>

              <track id="easjo"><source id="easjo"></source></track>
              1. 
                

              2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
              3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>