師居然讓我們做個溫度控制系統(tǒng),幸好這學(xué)期自己自學(xué)了32,所以覺得這還不是件困難的事。零零散散的寫了幾回,還么有在做好,各個模塊都調(diào)通了,所以只有收尾的工作可干了。 廢話少說,先上程序。 //主函數(shù) #include"iostm8s105k4.h" #include"qudong.h" #include"18b20.h" main() { Init_UART2(); hex_led(); Init_Timer4(); clock_hsi_16mhz();//將系統(tǒng)的時鐘設(shè)置為16MHZ key_inint();//按鍵掃描程序,開始想用中斷控制,發(fā)現(xiàn)效果不太好,所以改用按鍵掃描查詢模式 TIM2_Init(); //定時器2,產(chǎn)生2路PWM波,一路供繼電器控制熱地塊,另一路控制馬達攪拌水 // TIM3_Init(); asm("rim");//開全局中斷 while (1) { if(flag==1) { } key_scan(); set_pwm(); //改變占空比,來調(diào)節(jié)馬達和繼電器的開關(guān)速率 wendu= DS18B20_ReadTemperature();//將18b20的讀數(shù)讀取。因為讀取一個數(shù)據(jù)需要750ms,所以反應(yīng)速率還是超級慢的,之前用lm35,但發(fā)現(xiàn)就是個啃,用不了,也許我用錯了。 } } //驅(qū)動程序函數(shù) #include"iostm8s105k4.h" unsigned char HexTable[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; unsigned char code_hex[]={0x7f,0x0c,0xb6,0x9f,0xcc,0xdb,0xfb,0x0f,0xff,0xdf,0x0c,0x72}; unsigned char code_n[]={0xfb,0xf7,0xef,0xdf}; unsigned char time4_i; unsigned long int ad_sum=500; unsigned char set,flag; void clock_hsi_16mhz(void) { CLK_ICKR|=0x01; //開啟內(nèi)部HSI while(!(CLK_ICKR&0x02));//HSI準備就緒 CLK_SWR=0xe1; //HSI為主時鐘源 CLK_CKDIVR=0x00; //HSI不分頻 } void hex_led(void) //設(shè)置4個共陰數(shù)碼管引腳定義 { PE_DDR|=0x20; PE_CR1|=0x20; PE_CR2|=0x00; PE_ODR|=0x00; PC_DDR|=0xFF; PC_CR1|=0xFF; PC_CR2|=0x00; PC_ODR|=0x00; PB_DDR|=0x3C; PB_CR1|=0x3C; PB_CR2|=0x00; PB_ODR|=0x3C; } void dis_hex_led(unsigned char dat,unsigned char n) { PC_ODR=0x00; //由定時器4按照每2ms掃描一個數(shù)碼管 PE_ODR&=0x00; PB_ODR|=0x3c; PB_ODR&=code_n[n]; PC_ODR=code_hex[dat]; if(n!=1) PE_ODR&=~0x20; else PE_ODR|=0x20; if(ad_sum==1000) PE_ODR&=~0x20; } void Init_UART2(void) { UART2_CR1=0x00; UART2_CR2=0x00; UART2_CR3=0x00; // 設(shè)置波特率,必須注意以下幾點: // (1) 必須先寫B(tài)RR2 // (2) BRR1存放的是分頻系數(shù)的第11位到第4位, // (3) BRR2存放的是分頻系數(shù)的第15位到第12位,和第3位 // 到第0位 // 例如對于波特率位9600時,分頻系數(shù)=2000000/9600=208 // 對應(yīng)的十六進制數(shù)為00D0,BBR1=0D,BBR2=00 UART2_BRR2=0x0B;//以115.2kHz頻率發(fā)送數(shù)據(jù) UART2_BRR1=0x08; UART2_CR2=0x08;//允許接收,發(fā)送,開接收中斷 PD_DDR|=0x20; PD_CR1|=0x40; PD_CR2|=0x20; PD_ODR|=0x00; } void UART2_sendchar(unsigned char c)//串口通信助手打開,每次發(fā)送一個數(shù)據(jù) { while((UART2_SR & 0x80)==0x00); UART2_DR=c; } void UART2_sendhex(unsigned char dat) { UART2_sendchar('0'); UART2_sendchar('x'); UART2_sendchar(HexTable[dat>>4]); UART2_sendchar(HexTable[dat&0x0f]); UART2_sendchar(' '); } void UART2_sendstr(unsigned char *dat) { while(*dat!='\0') { UART2_sendchar(*dat); dat++; //delay2us(); } } void UART2_sendnum(unsigned char dat) { unsigned char dat_code[3]; dat_code[0]=dat/100; dat_code[1]=dat%100/10; dat_code[2]=dat%10; if(dat>=100) UART2_sendchar(HexTable[dat_code[0]]); if(dat>=10) UART2_sendchar(HexTable[dat_code[1]]); UART2_sendchar(HexTable[dat_code[2]]); } void Init_Timer4(void) { TIM4_CR1=0x01;//使能計數(shù)器 //TIM4_IER=0x00; TIM4_IER=0x01;//更新中斷使能 TIM4_EGR=0x01; TIM4_CNTR=255;//計數(shù)器值 TIM4_ARR=255;//自動重裝的值 TIM4_PSCR=0x07;//分頻值128分頻周期4ms } void key_inint(void) { PD_DDR&=~0x85; PD_CR1|=0x85; PD_CR2|=0x00; PF_DDR|=~0x10; PF_CR1|=0x10; PF_CR2|=0x00; PA_DDR|=0x06; PA_CR1|=0x06; PA_CR2|=0x06; PA_ODR|=0x00; } void delay(unsigned int i) { while(i--); } void set_key(void) { ++set; if(set==3) set=0; } void add_key(void) { switch(set) { case 0:ad_sum+=100;break; case 1:ad_sum+=10;break; case 2:ad_sum+=1;break; default: ad_sum+=0;break; } if(ad_sum>1000)ad_sum=1000; } void del_key(void) { switch(set) { case 0:ad_sum-=100;break; case 1:ad_sum-=10;break; case 2:ad_sum-=1;break; default: ad_sum-=0;break; } if(ad_sum<200)ad_sum=200; } void key_scan(void) { if((PF_IDR&0X10)!=0X10) { delay(200); if((PF_IDR&0X10)!=0X10) { PA_ODR^=0x02; if(flag==0) { flag=1; Init_UART2(); } switch(flag) { case 1:flag=2;break; case 2:flag=1; break; default:flag=1;break; } while((PF_IDR&0X10)!=0X10); } } if((PD_IDR&0x85)!=0x85) { delay(200); if((PD_IDR&0x85)!=0x85) { switch(PD_IDR&0x85) { case 0x84:PA_ODR^=0x02;del_key();break; case 0x81:PA_ODR^=0x02;add_key();break; case 0x05:PA_ODR^=0x02;set_key();break; default:break; } if(flag==2) { unsigned char sum_h,sum_l; sum_h=ad_sum/100; sum_l=ad_sum%100/10; UART2_sendnum(sum_h); UART2_sendnum(sum_l); sum_l=ad_sum%10; UART2_sendnum(sum_l); } while((PD_IDR&0x85)!=0x85); } } } void TIM2_Init() { TIM2_CCMR2 = TIM2_CCMR2 | 0x70;// Output modePWM2. //通道2被設(shè)置成比較輸出方式 // OC2M = 111,為PWM模式2, // 向上計數(shù)時,若計數(shù)器小于比較值,為無效電平 // 即當計數(shù)器在0到比較值時,輸出為1,否則為0 TIM2_CCMR1 = TIM2_CCMR1 | 0x70; TIM2_CCER1 = TIM2_CCER1 | 0x33;// CC polarity low,enable PWMoutput */ // CC2P = 1,低電平為有效電平 // CC2E = 1,開啟輸出引腳 //初始化自動裝載寄存器,決定PWM方波的頻率,F(xiàn)pwm=16000000/1000=16kHZ TIM2_ARRH = 1000/256; TIM2_ARRL = 1000%256; TIM2_CCR1H = 0; TIM2_CCR1L = 0; //初始化比較寄存器,決定PWM方波的占空比 TIM2_CCR2H = 0; TIM2_CCR2L = 0; //初始化時鐘分頻器為1,即計數(shù)器的時鐘頻率為Fmaster=4MHZ TIM2_PSCR = 0; //啟動計數(shù) TIM2_CR1 = TIM2_CR1 | 0x01; } void set_pwm(void) { unsigned char i; for(i=0;i<255;i++) { TIM2_CCR1H = 1; TIM2_CCR1L = i; TIM2_CCR2H = 1; TIM2_CCR2L = i; // delay(100); } // 下面的循環(huán)將占空比逐漸從50%遞減到0 for(i=255;i>0;i--) { TIM2_CCR2H = 3; TIM2_CCR2L = i; TIM2_CCR1H = 3; TIM2_CCR1L = i; //delay(100); } } #pragma vector=TIM4_OVR_UIF_vector//0x19 __interrupt void TIM4_OVR_UIF_IRQHandler(void)//對應(yīng)IAP的中斷地址:0x8060 { ++time4_i; TIM4_SR=0x00; switch(time4_i) { case 1:dis_hex_led(11,3);break; case 2: { dis_hex_led(ad_sum/100,0); } break; case 3: dis_hex_led(ad_sum%100/10,1); break; case 4: dis_hex_led(ad_sum%10,2);time4_i=0; break; default:time4_i=0;break; } //return; } //溫度采集程序 #include"iostm8s105k4.h" /******** STM8S-Discovery DS18B20 Test ******** * 版本.........: 1.0 * 作者.........: 陳利棟 * 目標.........: STM8S105C6 * 文件名.......: main.c * 編譯器.......: IAR for STM8 V1.1 * 創(chuàng)建時間.....: 2010.09.10 * 最后修改.....: 2010.09.10 **********************************************/ #define DS18B20_DQ_OUT PB_DDR_DDR0 = 1 //輸出 #define DS18B20_DQ_IN PB_DDR_DDR0 = 0 //輸入 #define DS18B20_DQ_HIGH PB_ODR_ODR0 = 1 //拉高 #define DS18B20_DQ_LOW PB_ODR_ODR0 = 0 //拉低 #define DS18B20_DQ_PULL_UP PB_CR1_C10 = 1 //上拉 #define DS18B20_DQ_FLOATING PB_CR1_C10 = 0 //浮空 #define DS18B20_DQ_PUSH_PULL PB_CR1_C10 = 1 //推挽 #define DS18B20_DQ_OPEN_DRAIN PB_CR1_C10 = 0 //開漏 #define DS18B20_DQ_VALUE PB_IDR_IDR0 //DQ值 float wendu; unsigned char state; void _delay_us(unsigned int i) { i *= 3; while(--i); } void _delay_ms(unsigned int i) { while(i--) { _delay_us(1000); } } void DS18B20_Init(void) { DS18B20_DQ_OUT; DS18B20_DQ_PUSH_PULL; DS18B20_DQ_HIGH; _delay_us(10); DS18B20_DQ_LOW; _delay_us(600); //復(fù)位脈沖 DS18B20_DQ_IN; DS18B20_DQ_PULL_UP; _delay_us(100); while(DS18B20_DQ_VALUE == 1); _delay_us(400); } void DS18B20_WriteByte(unsigned char _data) { unsigned char i = 0; DS18B20_DQ_OUT; for (i = 0; i < 8; i++) { DS18B20_DQ_LOW; _delay_us(2); if (_data & 0x01) { DS18B20_DQ_HIGH; } _data >>= 1; _delay_us(60); DS18B20_DQ_HIGH; } } unsigned char DS18B20_ReadByte(void) { unsigned char i = 0, _data = 0; for (i = 0; i < 8; i++) { DS18B20_DQ_OUT; DS18B20_DQ_LOW; _delay_us(5); _data >>= 1; DS18B20_DQ_HIGH; DS18B20_DQ_IN; if (DS18B20_DQ_VALUE) { _data |= 0x80; } DS18B20_DQ_OUT; DS18B20_DQ_HIGH; _delay_us(60); } return _data; } float DS18B20_ReadTemperature(void) { unsigned char temp = 0; float t = 0; DS18B20_Init(); DS18B20_WriteByte(0xcc); DS18B20_WriteByte(0x44); DS18B20_Init(); DS18B20_WriteByte(0xcc); DS18B20_WriteByte(0xbe); temp = DS18B20_ReadByte(); t = (((temp & 0xf0) >> 4) + (temp & 0x07) * 0.125); temp = DS18B20_ReadByte(); t += ((temp & 0x0f) << 4); return t; } void TIM3_Init() { TIM3_EGR=0x01; //手動產(chǎn)生更新事件,重新初始化計數(shù)器,并允許產(chǎn)生一個更新事件 //設(shè)置定時器初值 TIM3_CNTRH=0; //不能使用TIM3_CNTR直接設(shè)值, TIM3_CNTRL=0; //設(shè)定自動重裝寄存器值 //這里得注意不能使用TIM2_ARR的方式進行設(shè)值,TIM2是十六位的。 //如TIM2_ARR=0xFA,實際上是賦給高字節(jié)了,TIM2_ARRH=0xFA,而不是想象中的賦給低字節(jié)。 TIM3_ARRH=0x00; //31250 16MHz / 125 = 128000Hz (1S) TIM3_ARRL=0x0a; //0x007d 意味著每產(chǎn)生一次中斷時間為1MS TIM3_PSCR=0x07; //分頻128 TIM3_IER=0x01; //中斷允許位使能 TIM3_CR1=0x01; //使能計時器 } #pragma vector=TIM3_OVR_UIF_vector __interrupt void TIM3_OVF_IRQHandler(void) { TIM3_SR1 = 0x00; PA_ODR^=0x04; } |
歡迎光臨 (http://www.torrancerestoration.com/bbs/) | Powered by Discuz! X3.1 |