中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

WordPress更改網(wǎng)站地址抖音seo排名系統(tǒng)哪個好用

WordPress更改網(wǎng)站地址,抖音seo排名系統(tǒng)哪個好用,泉州app開發(fā),網(wǎng)易云服務器STM32 DMA學習日記 寫于2024/9/28晚 文章目錄 STM32 DMA學習日記1. DMA簡介2. I/O方式2.1 程序查詢方式2.2 程序中斷方式2.3 DMA方式 3.DMA框圖4. 相關(guān)寄存器4.1 DMA中斷狀態(tài)寄存器(DMA_ISR)4.2 DMA中斷標志清除寄存器(DMA_IFCR)…

STM32 DMA學習日記

寫于2024/9/28晚

文章目錄

  • STM32 DMA學習日記
    • 1. DMA簡介
    • 2. I/O方式
      • 2.1 程序查詢方式
      • 2.2 程序中斷方式
      • 2.3 DMA方式
    • 3.DMA框圖
    • 4. 相關(guān)寄存器
      • 4.1 DMA中斷狀態(tài)寄存器(DMA_ISR)
      • 4.2 DMA中斷標志清除寄存器(DMA_IFCR)
      • 4.3 DMA通道x傳輸數(shù)量寄存器(DMA_CNDTRx)
      • 4.4 DMA通道x配置寄存器(DMA_CCRx)
      • 4.5 DMA通道x外設(shè)地址寄存器(DMA_CPARx)
      • 4.6 DMA通道x存儲器地址寄存器(DMA_CMARx)
    • 5.例程解析
      • 5.1 DMA相關(guān)HAL庫驅(qū)動介紹

1. DMA簡介

DMA,全稱為:Direct Memory Access,即直接存儲器訪問。DMA 傳輸方式無需 CPU 直接控制傳輸,也沒有中斷處理方式那樣保留現(xiàn)場和恢復現(xiàn)場的過程,通過硬件為 RAM 與 I/O 設(shè)備開辟一條直接傳送數(shù)據(jù)的通路,能使 CPU 的效率大為提高。是計算機的4種I/O方式中的一種。

2. I/O方式

輸入/輸出系統(tǒng)實現(xiàn)主機與I/O設(shè)備之間的數(shù)據(jù)傳送,可以采用不同的控制方式,各種方式在代價、性能、解決問題的著重點等方面各不相同,常用的I/O方式有程序查詢、程序中斷、DMA和通道等,其中前兩種方式更依賴于CPU中程序指令的執(zhí)行。下面我們來簡介一下計算機組成原理中的4中I/O方式中的前三種。

2.1 程序查詢方式

信息交換的控制完全由CPU執(zhí)行程序?qū)崿F(xiàn),程序查詢方式接口中設(shè)置一個數(shù)據(jù)緩沖寄存器(數(shù)據(jù)端口)和一個設(shè)備狀態(tài)寄存器(狀態(tài)端口)。主機進行I/O操作時,先發(fā)出詢問信號,讀取設(shè)備的狀態(tài)并根據(jù)設(shè)備狀態(tài)決定下一步操作究竟是進行數(shù)據(jù)傳送還是等待。
{5A3B2F5B-BA0A-4474-99E4-FE472847AD72}

程序查詢方式的工作流程如下(見圖7.2):

  • ①CPU執(zhí)行初始化程序,并預置傳送參數(shù)。
  • ②向I/O接口發(fā)出命令字,啟動I/O設(shè)備。
  • ③從外設(shè)接口讀取其狀態(tài)信息。
  • ④CPU不斷查詢I/O設(shè)備狀態(tài),直到外設(shè)準備就緒。
  • ⑤傳送一次數(shù)據(jù)。
  • ⑥修改地址和計數(shù)器參數(shù)。
  • ⑦判斷傳送是否結(jié)束,若未結(jié)束轉(zhuǎn)第③步,直到計數(shù)器為0

在這種控制方式下,CPU一旦啟動I/O,就必須停止現(xiàn)行程序的運行,并在現(xiàn)行程序中插入一段程序。程序查詢方式的主要特點是CPU有“踏步”等待現(xiàn)象,CPU與I/O串行工作。這種方式的接口設(shè)計簡單、設(shè)備量少,但CPU在信息傳送過程中要花費很多時間來查詢和等待,而且在一段時間內(nèi)只能和一臺外設(shè)交換信息,效率大大降低。

2.2 程序中斷方式

程序中斷方式的思想:CPU在程序中安排好在某個時機啟動某臺外設(shè),然后CPU繼續(xù)執(zhí)行當前的程序,不需要像查詢方式那樣一直等待外設(shè)準備就緒。一旦外設(shè)完成數(shù)據(jù)傳送的準備工作,就主動向CPU發(fā)出中斷請求,請求CPU為自己服務。在可以響應中斷的條件下,CPU暫時中止正在執(zhí)行的程序,轉(zhuǎn)去執(zhí)行中斷服務程序為外設(shè)服務,在中斷服務程序中完成一次主機與外設(shè)之間的數(shù)據(jù)傳送,傳送完成后,CPU返回原來的程序,如圖7.3所示。

{A0A27BD6-8E2C-47B8-B064-6174455FE4C6}

2.3 DMA方式

DMA方式是一種完全由硬件進行成組信息傳送的控制方式,它具有程序中斷方式的優(yōu)點,即在數(shù)據(jù)準備階段,CPU與外設(shè)并行工作。DMA方式在外設(shè)與內(nèi)存之間開辟一條“直接數(shù)據(jù)通道”,信息傳送不再經(jīng)過CPU,降低了CPU在傳送數(shù)據(jù)時的開銷,因此稱為直接存儲器存取方式。

由于數(shù)據(jù)傳送不經(jīng)過CPU,也就不需要保護、恢復CPU現(xiàn)場等煩瑣操作。

這種方式適用于磁盤、顯卡、聲卡、網(wǎng)卡等高速設(shè)備大批量數(shù)據(jù)的傳送,它的硬件開銷比較大。在DMA方式中,中斷的作用僅限于故障和正常傳送結(jié)束時的處理。

DMA控制器的組成
在DMA方式中,對數(shù)據(jù)傳送過程進行控制的硬件稱為DMA控制器(DMA接口)。當I/O設(shè)備需要進行數(shù)據(jù)傳送時,通過DMA控制器向CPU提出DMA傳送請求,CPU響應之后將讓出系統(tǒng)總線,由DMA控制器接管總線進行數(shù)據(jù)傳送。其主要功能如下:

  1. 接受外設(shè)發(fā)出的DMA請求,并向CPU發(fā)出總線請求。
  2. CPU響應并發(fā)出總線響應信號,DMA接管總線控制權(quán),進入DMA操作周期。
  3. 確定傳送數(shù)據(jù)的主存單元地址及長度,并自動修改主存地址計數(shù)和傳送長度計數(shù)。
  4. 規(guī)定數(shù)據(jù)在主存和外設(shè)間的傳送方向,發(fā)出讀寫等控制信號,執(zhí)行數(shù)據(jù)傳送操作。
  5. 向CPU報告DMA操作結(jié)束。

{243E987B-4BAA-4FD4-94B8-E566F38635D2}

DMA方式和中斷方式的區(qū)別
DMA方式和中斷方式的重要區(qū)別如下:
①中斷方式是程序的切換,需要保護和恢復現(xiàn)場;而DMA方式不中斷現(xiàn)行程序,無需保護現(xiàn)場,除了預處理和后處理,其他時候不占用任何CPU資源。
②對中斷請求的響應只能發(fā)生在每條指令執(zhí)行結(jié)束時(執(zhí)行周期后);而對DMA請求的響應可以發(fā)生在任意一個機器周期結(jié)束時(取指、間址、執(zhí)行周期后均可)。
③中斷傳送過程需要CPU的干預;而DMA傳送過程不需要CPU的干預,因此數(shù)據(jù)傳輸率非常高,適合于高速外設(shè)的成組數(shù)據(jù)傳送。④DMA請求的優(yōu)先級高于中斷請求。
⑤中斷方式具有處理異常事件的能力,而DMA方式僅局限于大批數(shù)據(jù)的傳送。
⑥從數(shù)據(jù)傳送來看,中斷方式靠程序傳送,DMA方式靠硬件傳送。

{18B39D76-9DB5-48FE-98C8-F24C90E0503E}

3.DMA框圖

STM32F103ZET6 有兩個 DMA 控制器,DMA1 和 DMA2,本章,我們僅針對 DMA1 進行介紹。

下面先來學習 DMA 控制器框圖,通過學習 DMA 控制器框圖會有一個很好的整體掌握,同時對之后的編程也會有一個清晰的思路。

在這里插入圖片描述

圖中,我們標記了 3 處位置,起作用分別是:

DMA 請求

如果外設(shè)想要通過 DMA 來傳輸數(shù)據(jù),必須先給 DMA 控制器發(fā)送 DMA 請求,DMA 收到請求信號之后,控制器會給外設(shè)一個應答信號,當外設(shè)應答后且 DMA 控制器收到應答信號之后,就會啟動 DMA 的傳輸,直到傳輸完畢。

STM32F103 共有 DMA1 和 DMA2 兩個控制器,DMA1 有 7 個通道,DMA2 有 5 個通道,不同的 DMA 控制器的通道對應著不同的外設(shè)請求,這決定了我們在軟件編程上該怎么設(shè)置,具體見表 29.1.1.1DMA 請求映像表。

{A9D5348C-6521-4BD8-9EFD-57C963995C81}

{8EF4040D-7D98-4D0A-8C12-D5751D22E327}

② 通道

DMA 具有 12 個獨立可編程的通道,其中 DMA1 有 7 個通道,DMA2 有 5 個通道,每個通道對應不同的外設(shè)的 DMA 請求。雖然每個通道可以接收多個外設(shè)的請求,但是同一時間只能接收一個,不能同時接收多個。

③ 仲裁器

當發(fā)生多個 DMA 通道請求時,就意味著有先后響應處理的順序問題,這個就由仲裁器管理。仲裁器管理 DMA 通道請求分為兩個階段。第一階段屬于軟件階段,可以在 DMA_CCRx寄存器中設(shè)置,有 4 個等級:非常高,高,中和低四個優(yōu)先級。第二階段屬于硬件階段,如果兩個或以上的 DMA 通道請求設(shè)置的優(yōu)先級一樣,則他們優(yōu)先級取決于通道編號,編號越低優(yōu)先權(quán)越高,比如通道 0 高于通道 1。在大容量產(chǎn)品和互聯(lián)型產(chǎn)品中,DMA1 控制器擁有高于 DMA2 控制器的優(yōu)先級。

4. 相關(guān)寄存器

4.1 DMA中斷狀態(tài)寄存器(DMA_ISR)

{7039A4D7-705B-45CC-B3B4-9B0408D11909}

該寄存器是查詢當前 DMA 傳輸?shù)臓顟B(tài),我們常用的是 TCIFx 位,即通道 DMA 傳輸完成與否的標志。注意此寄存器為只讀寄存器,所以在這些位被置位之后,只能通過其他的操作來清除。

4.2 DMA中斷標志清除寄存器(DMA_IFCR)

{DDC9A71E-0464-418B-88BB-88782AC0B85D}

該寄存器是用來清除 DMA_ISR 的對應位的,通過寫 0 清除。在 DMA_ISR 被置位后,我們必須通過向該寄存器對應的位寫 1 來清除。

4.3 DMA通道x傳輸數(shù)量寄存器(DMA_CNDTRx)

{94303E5E-A1E8-4446-B36C-47929AC012A3}

4.4 DMA通道x配置寄存器(DMA_CCRx)

image-20240929114707514

該寄存器控制著 DMA 很多相關(guān)信息,包括數(shù)據(jù)寬度、外設(shè)及存儲器寬度、通道優(yōu)先級、增量模式、傳輸方向、中斷允許、使能等,所以說 DMA_CCRx 是 DMA 傳輸?shù)暮诵目刂萍拇嫫鳌?/p>

4.5 DMA通道x外設(shè)地址寄存器(DMA_CPARx)

image-20240929114804484

該寄存器是用來存儲 STM32 外設(shè)的地址,比如我們平常使用串口 1,那么該寄存器必須寫入 0x40013804(其實就是&USART1_DR)。其他外設(shè)就可以修改成其他對應外設(shè)地址就好了。

4.6 DMA通道x存儲器地址寄存器(DMA_CMARx)

DMA通道x存儲器地址寄存器用來存放存儲器的地址,該寄存器和 DMA_CPARx差不多,所以就不列出來了。舉個應用的例子,在程序中,我們使用到一個 g_sendbuf[5200]數(shù)組來做存儲器,那么我們在 DMA_CMARx 中寫入&g_sendbuf 即可。

5.例程解析

5.1 DMA相關(guān)HAL庫驅(qū)動介紹

驅(qū)動函數(shù)關(guān)聯(lián)寄存器功能描述
__HAL_RCC_DMAx_CLK_ENABLE(…)RCC_AHBENR使能DMAx時鐘
HAL_DMA_Init(…)DMA_CCR初始化DMA
HAL_DMA_Start_IT(…)DMA_CCR/CPAR/CMAR/CNDTR開始DMA傳輸
__HAL_LINKDMA(…)用來連接DMA和外設(shè)句柄
HAL_UART_Transmit_DMA(…)CCR/CPAR/CMAR/CNDTR/USART_CR3使能DMA發(fā)送,啟動傳輸
__HAL_DMA_GET_FLAG(…)DMA_ISR查詢DMA傳輸通道的狀態(tài)
__HAL_DMA_ENABLE(…)DMA_CCR(EN)使能DMA外設(shè)
__HAL_DMA_DISABLE(…)DMA_CCR(EN)失能DMA外設(shè)

DMA外設(shè)相關(guān)結(jié)構(gòu)體:DMA_HandleTypeDef 和 DMA_InitTypeDef

typedef struct __DMA_HandleTypeDef
{DMA_Channel_TypeDef   *Instance;               /*!< Register base address 寄存器基地址 */DMA_InitTypeDef       Init;                     /*!< DMA communication parameters DMA參數(shù) */ } DMA_HandleTypeDef;    
typedef struct
{uint32_t Direction				/* DMA傳輸方向 */uint32_t PeriphInc				/* 外設(shè)地址(非)增量 */uint32_t MemInc					/* 存儲器地址(非)增量*/uint32_t PeriphDataAlignment	/* 外設(shè)數(shù)據(jù)寬度 */uint32_t MemDataAlignment		/* 存儲器數(shù)據(jù)寬度 */uint32_t Mode					/* 操作模式 */uint32_t Priority				/* DMA通道優(yōu)先級 */} DMA_InitTypeDef;

以DMA方式傳輸串口數(shù)據(jù)配置步驟

  1. 使能DMA時鐘:__HAL_RCC_DMA1_CLK_ENABLE
  2. 初始化DMA:HAL_DMA_Init函數(shù)初始化DMA相關(guān)參數(shù) __HAL_LINKDMA函數(shù)連接DMA和外設(shè)
  3. 使能串口的DMA發(fā)送,啟動傳輸:HAL_UART_Transmit_DMA
  4. 查詢DMA傳輸狀態(tài):__HAL_DMA_GET_FLAG 查詢通道傳輸狀態(tài) __ HAL_DMA_GET_COUNTER 獲取當前傳輸剩余數(shù)據(jù)量
  5. DMA中斷使用:HAL_NVIC_EnableIRQ HAL_NVIC_SetPriority編寫中斷服務函數(shù) xxx_IRQHandler
DMA_HandleTypeDef  g_dma_handle;            /* DMA句柄 */
extern UART_HandleTypeDef g_uart1_handle;   /* UART句柄 *//*** @brief       串口TX DMA初始化函數(shù)*   @note      這里的傳輸形式是固定的, 這點要根據(jù)不同的情況來修改*              從存儲器 -> 外設(shè)模式/8位數(shù)據(jù)寬度/存儲器增量模式** @param       dmax_chy    : DMA的通道, DMA1_Channel1 ~ DMA1_Channel7, DMA2_Channel1 ~ DMA2_Channel5*                            某個外設(shè)對應哪個DMA, 哪個通道, 請參考<<STM32中文參考手冊 V10>> 10.3.7節(jié)*                            必須設(shè)置正確的DMA及通道, 才能正常使用! * @retval      無*/
void dma_init(DMA_Channel_TypeDef* DMAx_CHx)
{if ((uint32_t)DMAx_CHx > (uint32_t)DMA1_Channel7)     /* 大于DMA1_Channel7, 則為DMA2的通道了 */{__HAL_RCC_DMA2_CLK_ENABLE();                      /* DMA2時鐘使能 */}else {__HAL_RCC_DMA1_CLK_ENABLE();                      /* DMA1時鐘使能 */}__HAL_LINKDMA(&g_uart1_handle, hdmatx, g_dma_handle);           /* 將DMA與USART1聯(lián)系起來(發(fā)送DMA) *//* Tx DMA配置 */g_dma_handle.Instance = DMAx_CHx;                               /* USART1_TX使用的DMA通道為: DMA1_Channel4 */g_dma_handle.Init.Direction = DMA_MEMORY_TO_PERIPH;             /* DIR = 1 , 存儲器到外設(shè)模式 */g_dma_handle.Init.PeriphInc = DMA_PINC_DISABLE;                 /* 外設(shè)非增量模式 */g_dma_handle.Init.MemInc = DMA_MINC_ENABLE;                     /* 存儲器增量模式 */g_dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;    /* 外設(shè)數(shù)據(jù)長度:8位 */g_dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;       /* 存儲器數(shù)據(jù)長度:8位 */g_dma_handle.Init.Mode = DMA_NORMAL;                            /* 外設(shè)流控模式 */g_dma_handle.Init.Priority = DMA_PRIORITY_MEDIUM;               /* 中等優(yōu)先級 */HAL_DMA_Init(&g_dma_handle);
}

main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./USMART/usmart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./BSP/DMA/dma.h"const uint8_t TEXT_TO_SEND[] = {"正點原子 STM32 DMA 串口實驗"}; /* 要循環(huán)發(fā)送的字符串 */
#define SEND_BUF_SIZE       (sizeof(TEXT_TO_SEND) + 2) * 200    /* 發(fā)送數(shù)據(jù)長度, 等于sizeof(TEXT_TO_SEND) + 2的200倍. */uint8_t g_sendbuf[SEND_BUF_SIZE];           /* 發(fā)送數(shù)據(jù)緩沖區(qū) */
extern DMA_HandleTypeDef  g_dma_handle;     /* DMA句柄 */
extern UART_HandleTypeDef g_uart1_handle;   /* UART句柄 */int main(void)
{uint8_t  key = 0;uint16_t i, k;uint16_t len;uint8_t  mask = 0;float pro = 0;          /* 進度 */HAL_Init();                         /* 初始化HAL庫 */sys_stm32_clock_init(RCC_PLL_MUL9); /* 設(shè)置時鐘, 72Mhz */delay_init(72);                     /* 延時初始化 */usart_init(115200);                 /* 串口初始化為115200 */led_init();                         /* 初始化LED */lcd_init();                         /* 初始化LCD */key_init();                         /* 初始化按鍵 */dma_init(DMA1_Channel4);            /* 初始化串口1 TX DMA */lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);lcd_show_string(30, 70, 200, 16, 16, "DMA TEST", RED);lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);lcd_show_string(30, 110, 200, 16, 16, "KEY0:Start", RED);len = sizeof(TEXT_TO_SEND);k = 0;for (i = 0; i < SEND_BUF_SIZE; i++) /* 填充ASCII字符集數(shù)據(jù) */{if (k >= len)   /* 入換行符 */{if (mask){g_sendbuf[i] = 0x0a;k = 0;}else{g_sendbuf[i] = 0x0d;mask++;}}else     /* 復制TEXT_TO_SEND語句 */{mask = 0;g_sendbuf[i] = TEXT_TO_SEND[k];k++;}}i = 0;while (1){key = key_scan(0);if (key == KEY0_PRES)       /* KEY0按下 */{printf("\r\nDMA DATA:\r\n");lcd_show_string(30, 130, 200, 16, 16, "Start Transimit....", BLUE);lcd_show_string(30, 150, 200, 16, 16, "   %", BLUE);    /* 顯示百分號 */HAL_UART_Transmit_DMA(&g_uart1_handle, g_sendbuf, SEND_BUF_SIZE);/* 等待DMA傳輸完成,此時我們來做另外一些事情,比如點燈  * 實際應用中,傳輸數(shù)據(jù)期間,可以執(zhí)行另外的任務 */while (1){if ( __HAL_DMA_GET_FLAG(&g_dma_handle, DMA_FLAG_TC4))   /* 等待 DMA1_Channel4 傳輸完成 */{__HAL_DMA_CLEAR_FLAG(&g_dma_handle, DMA_FLAG_TC4);HAL_UART_DMAStop(&g_uart1_handle);                  /* 傳輸完成以后關(guān)閉串口DMA */break;}pro = DMA1_Channel4->CNDTR; /* 得到當前還剩余多少個數(shù)據(jù) */len = SEND_BUF_SIZE;        /* 總長度 */pro = 1 - (pro / len);      /* 得到百分比 */pro *= 100;                 /* 擴大100倍 */lcd_show_num(30, 150, pro, 3, 16, BLUE);} lcd_show_num(30, 150, 100, 3, 16, BLUE);    /* 顯示100% */lcd_show_string(30, 130, 200, 16, 16, "Transimit Finished!", BLUE); /* 提示傳送完成 */}i++;delay_ms(10);if (i == 20){LED0_TOGGLE();  /* LED0閃爍,提示系統(tǒng)正在運行 */i = 0;}}
}
http://www.risenshineclean.com/news/53739.html

相關(guān)文章:

  • 如何給別人做網(wǎng)站成都私人網(wǎng)站制作
  • 巴中網(wǎng)站制作公司公司怎么做網(wǎng)站推廣
  • 輕博客網(wǎng)站開發(fā)去了外包簡歷就毀了嗎
  • 傳世手游新開服網(wǎng)站網(wǎng)站首頁不收錄
  • 做網(wǎng)站用什么后綴好網(wǎng)站模板
  • 淘寶網(wǎng)站建設(shè) 推廣 上海濟寧百度推廣開戶
  • thinkphp做雙語網(wǎng)站百度知道app官方下載
  • 成都優(yōu)化網(wǎng)站哪家公司好seo優(yōu)化網(wǎng)站的手段
  • 把自己做的網(wǎng)站進行app封包騰訊云域名注冊官網(wǎng)
  • 對小米網(wǎng)站的建設(shè)意見青島新聞最新今日頭條
  • 想注冊一個做網(wǎng)站的公司企業(yè)營銷
  • 開家做網(wǎng)站公司有哪些合肥關(guān)鍵詞排名提升
  • 修改公司網(wǎng)站東莞推廣公司
  • 深圳哪個公司做網(wǎng)站好網(wǎng)站關(guān)鍵詞seo費用
  • 網(wǎng)站制作零基礎(chǔ)學習3步打造seo推廣方案
  • 銅仁市城鄉(xiāng)住房與建設(shè)局網(wǎng)站什么是seo?
  • 織夢五彩婚紗源碼網(wǎng)_婚慶策劃網(wǎng)站php源碼今日油價92汽油價格
  • 網(wǎng)站開發(fā)情況百度公司排名多少
  • wordpress如何壓縮圖片優(yōu)化推廣服務
  • 做網(wǎng)站的要求貴陽百度seo點擊軟件
  • 做網(wǎng)站公司哪個品牌好免費推廣的方式有哪些
  • 教做世界美食的網(wǎng)站西安百度快速排名提升
  • 營銷型網(wǎng)站的名詞解釋寶雞seo排名
  • 微信開發(fā)者工具下載官網(wǎng)下載seo軟文代寫
  • u網(wǎng)站建設(shè)蘭州網(wǎng)絡seo
  • 大學網(wǎng)站html模板百度競價托管一月多少錢
  • 湘潭seo 推廣快湘潭磐石網(wǎng)絡圖片優(yōu)化軟件
  • 有沒有做任務一樣的網(wǎng)站兼職自媒體推廣渠道
  • 網(wǎng)頁安全站點設(shè)置游戲優(yōu)化軟件
  • 企業(yè)網(wǎng)站模板優(yōu)化中國十大品牌營銷策劃公司