單晶片實務運用
主題: AD590 溫度量測
班級: 四電機二 A 學號: 4980J081 姓名: 史宗平
指導老師: 陳大道
一 一 一
一、、、、
AD590 AD590 溫度量測 AD590 AD590 溫度量測 溫度量測電路圖 溫度量測 電路圖 電路圖 電路圖
二二
二二、、、、程式程式程式程式內容內容內容 內容
EX11_1_ADC_Manual.c:
//
*********************************************************************
**
// File : EX11_1_ADC_Man.C
// Purpose : 練習如何叫 Microchip C30 提供的 ADC 函式庫 //
// 使用的函式 :
// ConfigIntTimer1( )
// OpenTimer1( )
// BusyADC10()
// CloseADC10()
// ConfigintADC10()
// ConvertADC10()
// OpenADC10()
// ReadADC10()
// SetChanADC10()
//
// 動作 :
// 將 LCD 初始化成 2 行 5*7 文字模式
// 使用 C30EVM_LCD.c 中的副程式顯示下列字串
//
// Exercise 11- ADC
// VR1:XXX VR2:YYY
//
// 將 Timer 1 規劃成 Period 為 1 ms 的 Timer
// 使用中斷的技巧 , 在 ISR 檢查是否已計時 1 秒
// 若是 , 則進行類比訊號轉換,並將轉換結果顯示於
LCD //
//
//
*********************************************************************
**
#define __dsPIC30F4011__
#include <p30F4011.h>
#include "C30EVM_LCD.h" // 將 LCD 函式的原型宣告檔案含入
#include <timer.h> // 將 Timer 函式的原型宣告檔案含入
#include <adc10.h> // 將 adc10 函式的原型宣告檔案含入
#define FCY 7372800 * 2 // 因為使用頻率為將外部 7.3728 MHz * 8 的模式 , 每一指令週期需 4 個 clock
// 所以 FCY = (7.3728 * 8 / 4 ) MHz = 7372800* 2
_FOSC(CSW_FSCM_OFF & XT_PLL8); // XT with 8xPLL oscillator, Failsafe clock off
_FWDT(WDT_OFF); // Watchdog timer disabled
_FBORPOR(PBOR_OFF & MCLR_EN); // Brown-out reset disabled, MCLR reset enabled
_FGS(CODE_PROT_OFF); // Code protect disabled
const char My_String1[]="Exercise 11- ADC" ; // 宣告字串於 Program Memory (因為 const 宣告)
char My_String2[]="VR1: VR2: " ; // 宣告字串於 Data Memory
unsigned int miliSec ;
void Init_ADC(void) ; void Show_ADC(void) ;
// union 宣告將使 8 位元變數 ByteAccess 與 SystemFlag 結構變數使用相同的記憶 體,
// 以利不同格式的位元運算需求
union {
unsigned char ByteAccess ; struct {
unsigned Bit0: 1 ; unsigned Bit1: 1 ;
unsigned Bit2: 1 ; unsigned unused : 5 ; } ;
} SystemFlag ;
//定義 OneSecond 旗標等同於 SystemFlag.Bit0 位元變數,故將其使用一個位元記 憶空間
#define OneSecond SystemFlag.Bit0
void _ISR _T1Interrupt(void) //Timer1中斷副程式 {
miliSec += 1 ;
if (miliSec == 1000) //每 1000 次將 OneSecond 旗標設定為 1 {
OneSecond = 1 ; miliSec = 0 ; }
IFS0bits.T1IF = 0 ; //清除中斷旗標
}
int main( void ) {
Init_ADC( ) ; // 將 ADC 進行初始
化設定
OpenLCD( ) ; // 使用 OpenLCD( )
對 LCD 模組作初始化設定
// 4 bits Data mode
// 5 * 7 Character
setcurLCD(0,0) ; // 使用 setcurLCD( )
設定游標於 (0,0)
putrsLCD( My_String1 ) ; // 將存在 Program
Memory 的字串使用
// putrsLCD( ) 印出至 LCD
setcurLCD(0,1) ; // 使用 setcurLCD( )
設定游標於 (0,1)
putrsLCD( My_String2 ) ; // 將存在 Data Memory
的字串使用
// putsLCD( ) 印出至 LCD
ConfigIntTimer1( T1_INT_PRIOR_7 & T1_INT_ON ) ; // Timer1 的中斷優 先等級設 7 (最高)
// Timer1 的中 斷 ON
OpenTimer1( T1_ON & T1_IDLE_STOP & T1_GATE_OFF & // Timer1 的 Period 設為每 1ms
T1_PS_1_1 & T1_SYNC_EXT_OFF & T1_SOURCE_INT , (FCY/ 1000) ) ;
OneSecond = 0 ;
while(1) {
if ( OneSecond ) // 詢問 Timer1 的
Period 時間是否已到
// 可以用軟體
模擬來檢查是否為準確的 1 ms {
OneSecond = 0 ;
Show_ADC( ) ; // 將類比轉換結果
顯示於 LCD 上
} }
}
/***********************************************/
// Subroutine to configure the A/D module
void Init_ADC(void) {
unsigned int Channel, PinConfig, Scanselect, Adcon3_reg, Adcon2_reg, Adcon1_reg;
ADCON1bits.ADON = 0; /* turn off ADC */
PinConfig = ENABLE_AN0_ANA; // Select port pins as analog inputs ADPCFG<15:0>
Adcon1_reg = ADC_MODULE_ON & // Turn on A/D module (ADON) ADC_IDLE_STOP & // ADC turned off during idle (ADSIDL)
ADC_FORMAT_INTG & // Output in integer format (FORM) ADC_CLK_MANUAL & // Conversion trigger manually (SSRC)
ADC_SAMPLE_INDIVIDUAL & // Sample channels individually (SIMSAM)
ADC_AUTO_SAMPLING_OFF; // Sample trigger manually (ASAM)
Adcon2_reg = ADC_VREF_AVDD_AVSS & // Voltage reference : +AVdd, -AVss (VCFG)
ADC_SCAN_OFF & // Scan off (CSCNA)
ADC_ALT_BUF_OFF & // Use fixed buffer (BUFM) ADC_ALT_INPUT_OFF & // Does not alternate between MUX A & MUX B (ALTS)
ADC_CONVERT_CH0 & // Convert only channel 0 (CHPS) ADC_SAMPLES_PER_INT_1; // 1 sample between interrupt (SMPI)
Adcon3_reg = ADC_SAMPLE_TIME_10 & // Auto-Sample time (SAMC) ADC_CONV_CLK_SYSTEM & // Use system clock (ADRC)
ADC_CONV_CLK_4Tcy; // Conversion clock = 4 Tcy (ADCS) // ADCS = 2*(154ns)/(1/Fcy)-1 = 3.5416
Scanselect = SCAN_NONE; // ADC scan no channel (ADCSSL)
OpenADC10(Adcon1_reg, Adcon2_reg, Adcon3_reg, PinConfig, Scanselect);
Channel = ADC_CH0_POS_SAMPLEA_AN0 & // CH0 Pos. : AN0, Neg. : Nominal Vref- Defined in ADCON2
ADC_CH0_NEG_SAMPLEA_NVREF ; // (ADCHS) SetChanADC10(Channel);
ConfigIntADC10(ADC_INT_DISABLE); // Disable ADC interrupt
}
/***********************************************/
// Subroutine to show Time on LCD
void Show_ADC(void) {
unsigned char dummy ; unsigned int ADCValue;
float T;
ADCON1bits.SAMP = 1; // start sampling ...
for ( dummy = 0 ; dummy < 100 ; dummy ++ );
ConvertADC10();
while (BusyADC10()); // conversion done?
//ADCValue = (ADCBUF0 >> 2); // get ADC value T=(50.0/1023.0)*ADCBUF0;
ADCValue=T*10;
setcurLCD(12,1) ; // Set LCD cursor
put_Num_LCD( ADCValue ) ; // 將類比轉換結果以十進位數字顯示至液晶顯
示器
C30EVM_LCD.c:
#include "C30EVM_LCD.h"
#include <p30F4011.h>
//
// Defines for I/O ports that provide LCD data & control
// PORTD[0:3]-->DB[4:7]: Higher order 4 lines data bus with bidirectional // : DB7 can be used as a BUSY flag
// PORTA,1 --> [E] : LCD operation start signal control // PORTA,2 --> [RW]: LCD Read/Write control
// PORTA,3 --> [RS]: LCD Register Select control
// : "0" for Instrunction register (Write), Busy Flag (Read) // : "1" for data register (Read/Write)
//
#define CPU_SPEED 16 // CPU speed is 16 Mhz !!
#define LCD_RS LATFbits.LATF0 // The definition of control pins
#define LCD_RW LATFbits.LATF1
#define LCD_E LATBbits.LATB7
#define LCD_E_MODE ADPCFGbits.PCFG7 // Set RB7 as digital I/O
#define DIR_LCD_RS TRISFbits.TRISF0 // Direction of control pins
#define DIR_LCD_RW TRISFbits.TRISF1
#define DIR_LCD_E TRISBbits.TRISB7
#define LCD_DATA LATD // PORTD[0:3] as LCD DB[4:7]
#define DIR_LCD_DATA TRISD // Direction of Databus
// LCD Module commands --- These settings can be found in the LCD datasheet
#define DISP_2Line_8Bit 0x0038 // 2 lines & 8 bits setting
#define DISP_2Line_4Bit 0x0028 // 2 lines & 4 bits setting
#define DISP_ON 0x00C // Display on
#define DISP_ON_C 0x00E // Display on, Cursor on
#define DISP_ON_B 0x00F // Display on, Cursor on, Blink cursor
#define DISP_OFF 0x008 // Display off
#define CLR_DISP 0x001 // Clear the Display
#define ENTRY_INC 0x006 // Entry Increment and Cursor Move
#define ENTRY_INC_S 0x007 // Entry Increment and Display Shift
#define ENTRY_DEC 0x004 // Entry Decrement and Cursor Move
#define ENTRY_DEC_S 0x005 // Entry Decrement and Display Shift
#define DD_RAM_ADDR 0x080 // Least Significant 7-bit are for address
#define DD_RAM_UL 0x080 // Upper Left coner of the Display
unsigned char Temp_CMD ; // Temperary Buffers for Command, unsigned char Str_Temp ; // for String,
int Temp_LCD_DATA ; // for PORT data (This will be restored after Communication w/ LCD)
//unsigned char Out_Mask ; //
void OpenLCD(void)
{
Temp_LCD_DATA = LCD_DATA ; // Save the Port Value of LCD_DATA
LCD_E_MODE =1 ; // Initialize RB7 as digital I/O
LCD_E = 0 ; //
LCD_DATA &= 0xfff0; // LCD DB[4:7] & RS & R/W -->
Low
DIR_LCD_DATA &= 0xfff0; // LCD DB[4:7} & RS & R/W are output function
DIR_LCD_E = 0; // Set E pin as output
DIR_LCD_RS = 0 ; DIR_LCD_RW = 0 ;
// Initialize the LCD following the standard operations // 1st
LCD_DATA &= 0xfff0 ; // Clear PORTDbits.RD0 ~ RD3 but save others by &
LCD_DATA |= 0x0003 ; // Send Data of 0x03 but keep others by |
LCD_CMD_W_Timing() ; // LCD Command Write Sequence Function
LCD_L_Delay() ; // Delay for long enough time
(4.1ms minimum)
// 2nd
LCD_DATA &= 0xfff0 ; // Clear PORTDbits.RD0 ~ RD3 LCD_DATA |= 0x0003 ; // Send Data of 0x03
LCD_CMD_W_Timing() ; // LCD Command Write Sequence Function
LCD_L_Delay() ; // Delay for long enough time
(100us minimum)
// 3rd
LCD_DATA &= 0xfff0 ; // Clear PORTDbits.RD0 ~ RD3 LCD_DATA |= 0x0003 ; // Send Data of 0x03
LCD_CMD_W_Timing() ; // LCD Command Write Sequence Function
LCD_L_Delay() ; // Delay for long enough time
(Not Required)
LCD_DATA &= 0xfff0 ; // Clear PORTDbits.RD0 ~ RD3 LCD_DATA |= 0x0002 ; // Send Data of 0x02 for 4-bit databus interface
LCD_CMD_W_Timing() ; LCD_L_Delay() ;
WriteCmdLCD(DISP_2Line_4Bit) ; // Configure LCD - 2 lines display &
4-bit long bus
LCD_S_Delay() ;
WriteCmdLCD(DISP_ON) ; // Configure LCD - Turn on display
LCD_S_Delay() ;
WriteCmdLCD(ENTRY_INC) ; // Configure LCD - Entry increment (to the right)
LCD_S_Delay() ;
WriteCmdLCD(CLR_DISP) ; // Configure LCD - Clear Display
LCD_L_Delay() ;
LCD_DATA = Temp_LCD_DATA ; // Restore Port Data (Useful if Port is shared, such as w/ LED)
}
//*********************************************
// _ ______________________________
// RS _>--<______________________________
// _____
// RW \_____________________________
// __________________
// E ____________/ \___
// _____________ ______
// DB _____________>---<______
//***********************************************
// Subroutine to
// Write Command to LCD module //
void WriteCmdLCD( unsigned char LCD_CMD) {
Temp_LCD_DATA = LCD_DATA ; // Save Port data to Temp buffer
Temp_CMD = (LCD_CMD & 0xF0)>>4 ; // Send high nibble to LCD bus LCD_DATA= (LCD_DATA & 0xfff0)|Temp_CMD ;
LCD_CMD_W_Timing () ;
Temp_CMD = LCD_CMD & 0x0F ; // Send low nibble to LCD bus
LCD_DATA= (LCD_DATA & 0xfff0)|Temp_CMD ; LCD_CMD_W_Timing () ;
LCD_DATA = Temp_LCD_DATA ; // Restore Port data
LCD_S_Delay() ; // Delay 100uS for
execution
}
//***********************************************
// Subroutine to
// Write Data to LCD module //
void WriteDataLCD( unsigned char LCD_CMD) {
Temp_LCD_DATA = LCD_DATA ; // Save Port data to Temp buffer
Temp_CMD = (LCD_CMD & 0xF0)>>4 ; // Send high nibble to LCD bus LCD_DATA= (LCD_DATA & 0xfff0)|Temp_CMD ;
LCD_DAT_W_Timing () ;
Temp_CMD = LCD_CMD & 0x0F ; // Send low nibble to LCD bus
LCD_DATA= (LCD_DATA & 0xfff0)|Temp_CMD ; LCD_DAT_W_Timing () ;
LCD_DATA = Temp_LCD_DATA ; // Restore Port data
LCD_S_Delay() ; // Delay 100uS for
execution
}
//***********************************************
// Subroutine to
// Write a character to LCD module
//
void putcLCD(unsigned char LCD_Char) {
WriteDataLCD(LCD_Char) ;
}
//***********************************************
// Subroutine to
// Write a command to LCD module // RS=0, R/W=0, E=H->L F(alling Edge)
void LCD_CMD_W_Timing( void ) // LCD Command writing timming
{
LCD_RS = 0 ; // Set for Command Input Nop();
LCD_RW = 0 ; Nop();
LCD_E = 1 ; Nop();
Nop();
Nop();
Nop();
LCD_E = 0 ; }
//***********************************************
// Subroutine to
// Write a command to LCD module // RS=1, R/W=0, E=H->L F(alling Edge)
void LCD_DAT_W_Timing( void ) // LCD Data writing timming {
LCD_RS = 1 ; // Set for Data Input Nop( );
LCD_RW = 0 ; Nop( );
LCD_E = 1 ; Nop( );
Nop( );
Nop( );
Nop( );
LCD_E = 0 ; }
//***********************************************
// Set Cursor position on LCD module // CurY = Line (0 or 1)
// CurX = Position ( 0 to 15) //
void setcurLCD(unsigned char CurX, unsigned char CurY) {
WriteCmdLCD( 0x80 + CurY * 0x40 + CurX) ; LCD_S_Delay() ;
}
//***********************************************
// Put a ROM string to LCD Module //
void putrsLCD( const char *Str ) {
while (1) {
Str_Temp = *Str ;
if (Str_Temp != 0x00 ) {
WriteDataLCD(Str_Temp) ; Str ++ ;
} else
return ; }
}
//***********************************************
// Put a RAM string to LCD Module //
void putsLCD( char *Str) {
while (1) {
Str_Temp = *Str ;
if (Str_Temp != 0x00 ) {
WriteDataLCD(Str_Temp) ; Str ++ ;
} else
return ; }
}
//***********************************************
// Put a byte in Hex format to LCD Module //
void puthexLCD(unsigned char HEX_Val) {
unsigned char Temp_HEX ;
Temp_HEX = (HEX_Val >> 4) & 0x0f ; // high nibble
if ( Temp_HEX > 9 )Temp_HEX += 0x37 ; // A~F
else Temp_HEX += 0x30 ; // 0~9
WriteDataLCD(Temp_HEX) ;
Temp_HEX = HEX_Val & 0x0f ; // low nibble if ( Temp_HEX > 9 )Temp_HEX += 0x37 ;
else Temp_HEX += 0x30 ;
WriteDataLCD(Temp_HEX) ; }
//***********************************************
// Put a byte in decimal format to LCD Module
// 0~99 Only. Uncomment the first 2 lines for hundreds
void put_Num_LCD( unsigned int The_Number ) {
unsigned char Temp_Char_100, Temp_Char_10, Temp_Char ;
Temp_Char_100 = The_Number /100 ; //取百位數的數字
putcLCD( Temp_Char_100 + '0' ) ; //轉換為 ASCII 編碼,'0'的編 碼加數字大小
Temp_Char_10 = (The_Number - Temp_Char_100*100) /10 ; //取 十位數的數字
putcLCD( Temp_Char_10 + '0' ) ;
Temp_Char = The_Number - ( Temp_Char_100*100 + Temp_Char_10 *
10 ) ; //取個位數的數字
putcLCD( 0x2e ) ;
putcLCD( Temp_Char + '0' ) ; }
// **********************************************
// Delay for atleast 10 ms
// **********************************************
void LCD_L_Delay(void) {
int L_Loop ;
for ( L_Loop = 0 ; L_Loop < 100 ; L_Loop ++ ) LCD_S_Delay( ) ;
}
// ***********************************************
// Delay for 100 us
// ***********************************************
void LCD_S_Delay(void) {
int S_Loop ; int Null_Var ;
for ( S_Loop = 0 ; S_Loop < 200 ; S_Loop ++ ) Null_Var += 1 ;
}
C30EVM_LCD.h:
void OpenLCD (void) ;
void WriteCmdLCD ( unsigned char ) ; void WriteDataLCD( unsigned char ) ; void putsLCD( char * ) ;
void putrsLCD( const char * ) ; void putcLCD( unsigned char ) ; void puthexLCD( unsigned char ) ; void put_Num_LCD( unsigned int ) ;
void setcurLCD( unsigned char , unsigned char ) ; // ( X-char, Y-line ) void LCD_CMD_W_Timing( void ) ;
void LCD_L_Delay( void ) ; void LCD_S_Delay( void ) ;
void LCD_DAT_W_Timing ( void ) ;
四 四 四
四、 、 、 、上 上 上課筆記 上 課筆記 課筆記 課筆記
五 五 五
五、 、 、 、實作 實作 實作結果 實作 結果 結果 結果
量測室內溫度 25.3 度