STM8單片機串口發送引腳和接收引腳分開使用

       在使用STM8S003單片機時,需要用到ADC採樣功能,STM8S003總共有5個ADC採樣口,但是其中兩個採樣口是和串口複用的,如果當ADC口用,就不能用串口,如果當串口用,就不能用ADC口。

       通過芯片管腳的原理圖可以看到PD5口可以當作模擬採樣第5通道使用,也可以用當做串口發送口使用。PD6口可以當做模擬採樣第6通道使用,也可以當做串口接收口使用。

      在項目中需要將串口當做AD口使用,但是也需要串口向外發送監控數據。AD功能和串口功能需要同時使用,於是想到,串口只用到了發送引腳,那麼能不能將串口的接收引腳當做AD功能用。這樣PD5口作爲串口發送引腳使用,PD6口作爲模擬採樣第6通道使用。

     先寫一個簡單的測試程序測試一下這種是否可行。

  首先將串口初始化程序中的,接收引腳和接收功能屏蔽掉。

將串口的接收引腳和接收功能屏蔽掉,串口只使用發送引腳和發送功能。

完整串口初始化代碼如下:

#include "uart.h"
#include "main.h"

//重新定向putchar函數,使支持printf函數
int putchar( int ch )
{
    while( !( UART1_SR & 0X80 ) );              //循環發送,直到發送完畢
    UART1_DR = ( u8 ) ch;
    return ch;
}
//串口只用發送口,不用接收口
void Uart1_IO_Init( void )
{
    PD_DDR |= ( 1 << 5 );                       //輸出模式 TXD
    PD_CR1 |= ( 1 << 5 );                       //推輓輸出
    
    //PD_DDR &= ~( 1 << 6 );                      //輸入模式 RXD
    //PD_CR1 &= ~( 1 << 6 );                      //浮空輸入
}

//波特率最大可以設置爲38400
void Uart1_Init( unsigned int baudrate )
{
    unsigned int baud;
    baud = 16000000 / baudrate;
    Uart1_IO_Init();
    UART1_CR1 = 0;      //禁止發送和接收
    UART1_CR2 = 0;      //8 bit
    UART1_CR3 = 0;      //1 stop
    UART1_BRR2 = ( unsigned char )( ( baud & 0xf000 ) >> 8 ) | ( ( unsigned char )( baud & 0x000f ) );
    UART1_BRR1 = ( ( unsigned char )( ( baud & 0x0ff0 ) >> 4 ) );
//    UART1_CR2_bit.REN = 1;                      //接收使能
    UART1_CR2_bit.TEN = 1;                      //發送使能
    UART1_CR2_bit.RIEN = 1;                     //接收中斷使能
}


//阻塞式發送函數
void SendChar( unsigned char dat )
{
    while( ( UART1_SR & 0x80 ) == 0x00 );       //發送數據寄存器空
    UART1_DR = dat;
}
//發送字符串
void SendString( unsigned char* s )
{
    while( 0 != *s )
    {
        SendChar( *s );
        s++;
    }
}

//接收中斷函數 中斷號18
#pragma vector = 20                             // IAR中的中斷號,要在STVD中的中斷號上加2
__interrupt void UART1_Handle( void )
{
    unsigned char res = 0;
  
    res = UART1_DR;
    UART1_SR &= ~( 1 << 5 );                    //RXNE 清零
  
}

下來將PD6引腳設置爲ADC採樣功能,完整初始化代碼如下:

#include "adc.h"
#include "main.h"

u16  DATAH = 0;                          //ADC轉換值高8位
u16  DATAL = 0;                          //ADC轉換值低8位
_Bool ADC_flag = 0;                      //ADC轉換成功標誌


//AD通道引腳初始化
void ADC_GPIO_Init( void )
{
    PD_DDR &= ~( 1 << 6 );              //PD6 設置爲輸入     AIN6 
    PD_CR1 &= ~( 1 << 6 );              //PD6 設置爲懸空輸入
    
}

void ADC_CH_Init( u8 ch )
{
    char l = 0;
    ADC_CR1  = 0x00;                    //fADC = fMASTER/2, 8Mhz  單次轉換,禁止轉換
    ADC_CSR  = ch + 1;                  //控制狀態寄存器 選擇要 AD輸入通道  如:PD2(AIN3)
    ADC_CR2  = 0x00;                    //默認左對齊 讀數據時先讀高在讀低
    ADC_TDRL = ( 1 << ( ch + 1 ) );     //禁止相應通道 施密特觸發功能 1左移ch+1位
    ADC_CR1 |= 0x01;                    //使能ADC並開始轉換
    ADC_CSR |= 0x20;                    //EOCIE 使能轉換結束中斷  EOC中斷使能
    for( l = 0; l < 100; l++ );         //延時,保證ADC模塊的上電完成 至少7us
    ADC_CR1 = ADC_CR1 | 0x01;           //再次將CR1寄存器的最低位置1 使能ADC 並開始轉換
}

//採集PD6電壓值  AIN6
u16 ReadVol_CH6( void )
{
    u16 voltage = 0;
    ADC_CH_Init( 5 );
    if( ADC_flag )
    {
        ADC_flag = 0;
        voltage = ( DATAH << 2 ) + DATAL ; //得到十位精度的數據  0--1024
        //ADC_CR1 = ADC_CR1 | 0x01;          //再次將CR1寄存器的最低位置1  啓動下一次轉換
    };
    return voltage;
}

//AD中斷服務函數 中斷號22
#pragma vector = 24                              // IAR中的中斷號,要在STVD中的中斷號上加2
__interrupt void ADC_Handle( void )
{
    ADC_CSR &= ~0x80;                            // 轉換結束標誌位清零  EOC
    //默認左對齊 讀數據時先讀高高8位 再讀低8位
    DATAH = ADC_DRH;                             // 讀出ADC結果的高8位
    DATAL = ADC_DRL;                             // 讀出ADC結果的低8位
    ADC_flag = 1;                                // ADC中斷標誌 置1
}

下來再主程序中就可以通過PD6引腳讀取AD採樣值,並通過PD5引腳輸出採樣到的值。
 

#include "iostm8s103F3.h"
#include "main.h"
#include "led.h"
#include "adc.h"
#include "stdio.h"
#include "delay.h"
#include "stdlib.h"
#include "uart.h"

u16 val_ch6 = 0;

void SysClkInit( void )
{
    CLK_SWR = 0xe1;                             //HSI爲主時鐘源  16MHz CPU時鐘頻率
    CLK_CKDIVR = 0x00;                          //CPU時鐘0分頻,系統時鐘0分頻
}

void main( void )
{
    u8 i=0;
    __asm( "sim" );                             //禁止中斷
    SysClkInit();
    delay_init( 16 );
    LED_GPIO_Init();
    Uart1_IO_Init();
    Uart1_Init( 9600 );
    ADC_GPIO_Init();
    __asm( "rim" );                             //開啓中斷
    while( 1 )
    {
        LED = ~LED; 
              
        for(i=0;i<10;i++)
        val_ch6 = ReadVol_CH6();
        delay_ms( 100 );
        
        printf( "%d\r\n", val_ch6);
        delay_ms( 200 );
    }
}

通過測試後發現這種方案可行,串口的發送功能和ADC採樣功能可以同時使用。也就是說在使用串口的時候,不一定發送引腳和接收引腳每次必須同時使用,可以根據情況,單獨使用串口的發送或者接收引腳。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章