|
剛剛用STM8S003做了個電壓表,互相交流一下。用到了ADC采樣及數碼管顯示。
電壓表.JPG (2.19 MB, 下載次數: 160)
下載附件
2017-4-22 11:15 上傳
STM8電壓表單片機源程序:
- #include<iostm8s003f3.h>
- unsigned int ms_count;
- unsigned char adcflag;
- unsigned int ADCData;
- unsigned int tmpin;
- unsigned int ADCBuff[3];
- /*******************************************************************************
- **函數名稱:void GPIO_Init()
- **功能描述:GPIO->功能引腳初始化
- **入口參數:無
- **輸出:無
- *******************************************************************************/
- void GPIO_Init()
- {
- PA_ODR &=0xf1; //PA1,2,3置零
- PA_DDR |=0x0e; //設置端口PA1,2,3的輸入輸出方向寄存器為輸出方向
- PA_CR1 |=0x0e; //PA1,2,3為推挽輸出
- PA_CR2 |=0x0e; //PA1,2,3是輸出速度最快為10MHz
-
- PB_ODR |=0x30; //滅PB4,5
- PB_DDR |=0x30; //設置端口PB4,5的輸入輸出方向寄存器為輸出方向
- PB_CR1 |=0x30; //PB4,5為推挽輸出
- PB_CR2 |=0x30; //PB4,5是輸出速度最快為10MHz
-
- PC_ODR |=0xf8; //滅PC3,4,5,6,7
- PC_DDR |=0xf8; //設置端口PC->3,4,5,6,7的輸入輸出方向寄存器為輸出方向
- PC_CR1 |=0xf8; //PC->3,4,5,6,7為推挽輸出
- PC_CR2 |=0xf8; //PC->3,4,5,6,7是輸出速度最快為10MHz
-
- PD_ODR |=0x02; //滅PD1
- PA_ODR &=0xe3; //PD2,3,4置零
- PD_DDR |=0x1e; //設置端口PD->1,2,3,4的輸入輸出方向寄存器為輸出方向
- PD_CR1 |=0x1e; //PD->1,2,3,4為推挽輸出
- PD_CR2 |=0x1e; //PD->1,2,3,4是輸出速度最快為10MHz
- }
- /*******************************************************************************
- **函數名稱:void SMG_Display(int num)
- **功能描述:SMG顯示函數
- **入口參數:int num
- **輸出:無
- *******************************************************************************/
- void SMG1_Display(unsigned char num)
- {
- switch(num)
- {
- case 0:
- PA_ODR &=0xf1; //PA1,2,3置零
- PB_ODR |=0x30; //PB4,5置高
- PC_ODR |=0xf8; //PC3,4,5,6,7置高
- PD_ODR |=0x02; //PD1置高
-
- PB_ODR &=0xcf; //PB4,5置低a,e
- PC_ODR &=0xa7; //PC3,4,6置低c,d,f
- PD_ODR &=0xfd; //PD1置低b
- //PA_ODR |=0x0e; //GIG1,2,3置高
- //PD_ODR |=0x1c; //GIG2 2,3,4置高
- break;
- case 1:
- PA_ODR &=0xf1; //PA1,2,3置零
- PB_ODR |=0x30; //PB4,5置高
- PC_ODR |=0xf8; //PC3,4,5,6,7置高
- PD_ODR |=0x02; //PD1置高
-
- //PB_ODR &=0xcf; //PB4,5置低a,e
- PC_ODR &=0xbf; //PC6置低c
- PD_ODR &=0xfd; //PD1置低b
- //PA_ODR |=0x0e; //GIG1,2,3置高
- //PD_ODR |=0x1c; //GIG2 2,3,4置高
- break;
- case 2:
- PA_ODR &=0xf1; //PA1,2,3置零
- PB_ODR |=0x30; //PB4,5置高
- PC_ODR |=0xf8; //PC3,4,5,6,7置高
- PD_ODR |=0x02; //PD1置高
-
- PB_ODR &=0xcf; //PB4,5置低a,e
- PC_ODR &=0x77; //PC3,7置低d,g
- PD_ODR &=0xfd; //PD1置低b
- //PA_ODR |=0x0e; //GIG1,2,3置高
- //PD_ODR |=0x1c; //GIG2 2,3,4置高
- break;
- case 3:
- PA_ODR &=0xf1; //PA1,2,3置零
- PB_ODR |=0x30; //PB4,5置高
- PC_ODR |=0xf8; //PC3,4,5,6,7置高
- PD_ODR |=0x02; //PD1置高
-
- PB_ODR &=0xef; //PB4置低a
- PC_ODR &=0x37; //PC3,6,7置低c,d,g
- PD_ODR &=0xfd; //PD1置低b
- //PA_ODR |=0x0e; //GIG1,2,3置高
- //PD_ODR |=0x1c; //GIG2 2,3,4置高
- break;
- case 4:
- PA_ODR &=0xf1; //PA1,2,3置零
- PB_ODR |=0x30; //PB4,5置高
- PC_ODR |=0xf8; //PC3,4,5,6,7置高
- PD_ODR |=0x02; //PD1置高
-
- //PB_ODR &=0xef; //PB4置低a
- PC_ODR &=0x2f; //PC4,6,7置低c,f,g
- PD_ODR &=0xfd; //PD1置低b
- //PA_ODR |=0x0e; //GIG1,2,3置高
- //PD_ODR |=0x1c; //GIG2 2,3,4置高
- break;
- case 5:
- PA_ODR &=0xf1; //PA1,2,3置零
- PB_ODR |=0x30; //PB4,5置高
- PC_ODR |=0xf8; //PC3,4,5,6,7置高
- PD_ODR |=0x02; //PD1置高
-
- PB_ODR &=0xef; //PB4置低a
- PC_ODR &=0x27; //PC3,4,6,7置低c,d,f,g
- //PD_ODR &=0xfd; //PD1置低b
- //PA_ODR |=0x0e; //GIG1,2,3置高
- //PD_ODR |=0x1c; //GIG2 2,3,4置高
- break;
- case 6:
- PA_ODR &=0xf1; //PA1,2,3置零
- PB_ODR |=0x30; //PB4,5置高
- PC_ODR |=0xf8; //PC3,4,5,6,7置高
- PD_ODR |=0x02; //PD1置高
-
- PB_ODR &=0xcf; //PB4,5置低a,e
- PC_ODR &=0x27; //PC3,4,6,7置低c,d,f,g
- //PD_ODR &=0xfd; //PD1置低b
- //PA_ODR |=0x0e; //GIG1,2,3置高
- //PD_ODR |=0x1c; //GIG2 2,3,4置高
- break;
- case 7:
- PA_ODR &=0xf1; //PA1,2,3置零
- PB_ODR |=0x30; //PB4,5置高
- PC_ODR |=0xf8; //PC3,4,5,6,7置高
- PD_ODR |=0x02; //PD1置高
-
- PB_ODR &=0xef; //PB4置低a
- PC_ODR &=0xbf; //PC6置低c
- PD_ODR &=0xfd; //PD1置低b
- //PA_ODR |=0x0e; //GIG1,2,3置高
- //PD_ODR |=0x1c; //GIG2 2,3,4置高
- break;
- case 8:
- PA_ODR &=0xf1; //PA1,2,3置零
- PB_ODR |=0x30; //PB4,5置高
- PC_ODR |=0xf8; //PC3,4,5,6,7置高
- PD_ODR |=0x02; //PD1置高
-
- PB_ODR &=0xcf; //PB4,5置低a,e
- PC_ODR &=0x27; //PC3,4,6,7置低c,d,f,g
- PD_ODR &=0xfd; //PD1置低b
- //PA_ODR |=0x0e; //GIG1,2,3置高
- //PD_ODR |=0x1c; //GIG2 2,3,4置高
- break;
- case 9:
- PA_ODR &=0xf1; //PA1,2,3置零
- PB_ODR |=0x30; //PB4,5置高
- PC_ODR |=0xf8; //PC3,4,5,6,7置高
- PD_ODR |=0x02; //PD1置高
-
- PB_ODR &=0xef; //PB4,5置低a,e
- PC_ODR &=0x27; //PC3,4,6,7置低c,d,f,g
- PD_ODR &=0xfd; //PD1置低b
- //PA_ODR |=0x0e; //GIG1,2,3置高
- //PD_ODR |=0x1c; //GIG2 2,3,4置高
- break;
- }
- }
- /*******************************************************************************
- **函數名稱:void ADC_Init()
- **功能描述:初始化ADC
- **入口參數:無
- **輸出:無
- *******************************************************************************/
- void ADC_Init()
- {
- PD_DDR_bit.DDR5 = 0; //設置PD->5 為輸入
- PD_CR1_bit.C15 = 0; //設置為懸空輸入
- PD_CR2_bit.C25 = 0; //設置中斷禁止
-
- ADC_CR1_bit.SPSEL = 3; //fmaster / 18 = 16MHZ / 18 = 888888HZ
- ADC_CR2_bit.ALIGN = 1; //RIGHT ALIGN
- ADC_CSR_bit.CH = 5; //SELECT AIN5
-
- ADC_CR1_bit.ADON = 1; //啟動ADC
- }
- /*******************************************************************************
- **函數名稱:void ADC_Data_Read(unsigned int *AD_Value)
- **功能描述:讀取ADC完成一次模數轉換結果
- **入口參數:unsigned int *AD_Value
- *AD_Value ->讀取ADC采樣數據的指針
- **輸出:無
- *******************************************************************************/
- void ADC_Data_Read(unsigned int *AD_Value)
- {
- ADC_CR1_bit.ADON = 1; //啟動ADC
-
- while(ADC_CSR_bit.EOC == 0); //等待轉換結束
- *AD_Value = ADC_DRH; //先讀取高8位
- *AD_Value = (unsigned int)((*AD_Value << 8) + ADC_DRL); //高8位與低8位相加,湊成16位數據
- }
- unsigned int ProcessVoltage(unsigned int tmpin)
- {
- unsigned long int Temp;
- Temp=tmpin;
- Temp*=330;
- Temp/=1024;
- return ((unsigned int)Temp)*11.3;
-
- }
- /*******************************************************************************
- **函數名稱:void Timer4Init()
- **功能描述:定時器4參數初始化
- **入口參數:無
- **輸出:無
- *******************************************************************************/
- void Timer4Init()
- {
-
- TIM4_IER_bit.UIE = 0; //禁止中斷
- TIM4_EGR_bit.UG = 0;
- TIM4_PSCR_bit.PSC = 7; // 設置TIM4的時鐘分頻系數為 128 即定時器時鐘 = 16000000 /128 = 125KHZ
-
- TIM4_ARR = 125; // 設定TIM4產生1毫秒的計數值
- TIM4_CNTR = 0x00; // 清除TIM4計數寄存器數值
-
-
- TIM4_SR_bit.UIF = 0; //清除中斷標志
- TIM4_SR_bit.TIF = 0;
- TIM4_CR1_bit.CEN = 1; //使能定時器4計數
- TIM4_CR1_bit.ARPE = 1; //使能預裝載
- TIM4_IER_bit.UIE = 1; // 使能更新中斷
- }
- /*******************************************************************************
- **函數名稱:void TIM2_Init()
- **功能描述:定時器2參數初始化
- **入口參數:無
- **輸出:無
- *******************************************************************************/
- void TIM2_Init()
- {
- TIM2_PSCR = 0x00; //定時器2預分頻數為 1 分頻,即定時器時鐘 = 系統時鐘 = 16MHz
- TIM2_ARRH = 0x3E; //設置1毫秒時間自動重載 16000 = 0x3e80
- TIM2_ARRL = 0x80; //
- TIM2_CNTRH = 0x00; //清除計數寄存器
- TIM2_CNTRL = 0x00; //
- TIM2_SR1 = 0x00; //清除所有的中斷標志
-
- }
- /*******************************************************************************
- **函數名稱:void TIM2_DelayMs(unsigned int ms)
- **功能描述:定時器2參進行精確延時,最小為1毫秒,最大65535
- **入口參數:unsigned int ms 1=< ms <= 65535
- **輸出:無
- *******************************************************************************/
- void TIM2_DelayMs(unsigned int ms)
- {
-
- TIM2_CR1 = 0x81; //啟動定時器2開始計數
- while(ms--)
- {
-
- while( !(TIM2_SR1 & 0x01)); //等待計數是否達到1毫秒
- TIM2_SR1 &= ~(0x01); //計數完成1毫秒,清除相應的標志
- }
- TIM2_CR1 = 0x00; //延時全部結束,關閉定時器2
- }
- /*******************************************************************************
- **函數名稱:void delay(unsigned int ms) Name: void delay(unsigned int ms)
- **功能描述:大概延時
- **入口參數:unsigned int ms 輸入大概延時數值
- **輸出:無
- *******************************************************************************/
- void delay(unsigned int ms)
- {
- unsigned int x , y;
- for(x = ms; x > 0; x--) /* 通過一定周期循環進行延時*/
- for(y = 1000 ; y > 0 ; y--);
- }
- /* 主函數 */
- int main(void)
- {
- asm("sim"); //關閉系統總中斷
- CLK_CKDIVR = 0x00; //CPUDIV = 1 HSIDIV = 1 內部時鐘 = 16Mhz
- //UART1_Init(9600); //調用串口初始化函數,并設置波特率為9600 bps
- //LED2Init(); //調用LED2初始化函數
- GPIO_Init();
- ADC_Init(); //調用ADC初始化函數
- TIM2_Init();
- Timer4Init(); //初始化定時器4
- asm("rim"); //打開系統總中斷
- unsigned char i=0;
- while(1)
- {
- if(adcflag == 1) //1秒定時時間到對使能ADC進行采樣
- {
- asm("sim"); //關系統總中斷
- ADC_Data_Read(&ADCData); //讀取ADC的采樣數值
- //Uart_SendString("ADC_DATA = " , 11); //發送字符串"ADC_DATA = "
- ADCBuff[2] = ProcessVoltage(ADCData) % 10;
- ADCBuff[1] = ProcessVoltage(ADCData) / 10 %10;
- ADCBuff[0] = ProcessVoltage(ADCData) / 100;
- //ADCBuff[2] =ADCData % 10;
- //ADCBuff[1] =ADCData / 10 %10;
- //ADCBuff[0] = ADCData / 100;
- /*ADCBuff[3] = ADCData % 10; //轉換成ASCII碼
- ADCBuff[2] = ADCData % 100 / 10;
- ADCBuff[1] = ADCData / 100 % 10 ;
- ADCBuff[0] = ADCData / 1000 ;
- */
- //ADCBuff[4] = 0x0d; //換行字符
- //ADCBuff[5] = 0x0a;
- //Uart_SendString(ADCBuff , 6); //向PC機發送ADC采樣數值
- adcflag = 0; //ADC采樣標志清除
- asm("rim"); //開系統總中斷,準備下次ADC采樣
- //PC_ODR ^= 0x80; //異或取反PC->3 ,使LED4進行周期性亮滅亮滅操作
- i=0;
- for(i=0;i<=100;i++)
- {
- SMG1_Display(ADCBuff[0]); //顯示個位
- PA_ODR |=0x02; //GIG1置高 亮第一個數碼管
- PC_ODR &=0xdf; //PC5置高
- TIM2_DelayMs(8);
- SMG1_Display(ADCBuff[1]); //顯示十分位
- PA_ODR |=0x04; //GIG2置高 亮第二個數碼管
- TIM2_DelayMs(8);
- SMG1_Display(ADCBuff[1]); //顯示百分位
- PA_ODR |=0x08; //GIG3置高 亮第二個數碼管
- TIM2_DelayMs(2);
- }
- i=0;
- //adcflag = 0; //ADC采樣標志清除
- }
- }
- }
- /** 定時器4中斷服務函數 */
- #pragma vector = 25
- __interrupt void TIM4_UPDATE_IRQHandler(void)
- {
- TIM4_SR_bit.UIF = 0; //清除中斷標志
- ms_count++;
-
- if(ms_count >= 800) //記錄1秒時間到
- {
- ms_count = 0;
- adcflag = 1; //設置ADC采樣標志
- }
- }
復制代碼
原理圖:http://www.zg4o1577.cn/bbs/dpj-128925-1.html
|
評分
-
查看全部評分
|