单片机程序.docx
《单片机程序.docx》由会员分享,可在线阅读,更多相关《单片机程序.docx(30页珍藏版)》请在冰豆网上搜索。
![单片机程序.docx](https://file1.bdocx.com/fileroot1/2023-1/23/e461f332-b1bf-4b20-b85f-093353f451b6/e461f332-b1bf-4b20-b85f-093353f451b61.gif)
单片机程序
电机PID算法应用实例
1.//=====PID参数设置======================
2.//运行PID时间 3
3.#define PIDCYC
(2)//20MS 运算一次
4.
5.#define AEKZ (int16)
(2) //此偏差范围内 不调节
6.#define AEKF (int16)(-2) //
7.
8.#define MAX_PID_VALUE_Z ((int16)(40)) //PID每次调节值的最大限制
9.#define MAX_PID_VALUE_F ((int16)(-40))
10.
11.#define MAX_ROP (V_MAX_PWM+2) //最大功率值 V_MAX_PWM=250
12.#define MIN_ROP (10) //最小功率值
13.//=======================================
14. //KA KB KC 参数不超过
15.#define KA (uint8)(10)
16.#define KB (uint8)(5)
17.#define KC (uint8)
(1)
18.
19.#define KP1 ((uint8)(240))
20.
21.//======================================
22.typedef struct MC_PID
23.{
24. int16 EkP1 ; //本次偏差
25. int16 EkP2 ; //上次偏差
26. int16 EkP3 ; //上上次偏差
27.
28. int16 SumP13 ;//当前 + 上上次 偏差运算值
29. int32 dwTmp1 ;
30.
31. uint16 SetRate ; //设定速度
32. uint16 CuRate ; //当前速度
33.
34.}tPID ;
35.
36.extern tPID tPidA ;
37.
38.#define EkP1 tPidA.EkP1
39.#define EkP2 tPidA.EkP2
40.#define EkP3 tPidA.EkP3
41.#define SumP13 tPidA.SumP13
42.#define dwTmp1 tPidA.dwTmp1
43.
44.#define SetRate tPidA.SetRate
45.#define CuRate tPidA.CuRate
46.
47.//****************************************
48.// 函数名称:
RumTempPid
49.// 函数功能:
温度控制PID
50.// 入口参数:
[Power为当前功率值] [速度设定值 当前值]
51.// 出口参数:
无
52.// 返 回 值:
功率值
53.//***************************************/
54.uint8 RumMotorPid(uint8 Power,uint16 SetValue,uint16 CuValue)
55.{
56. uint16 wTmp1 ;
57.
58. //F_EK1 = 0 设定 > 当前
59. //F_EK1 = 1 设定 < 当前
60. EkP3 = EkP2 ;
61. EkP2 = EkP1 ;
62.// F_EK3 = F_EK2 ;
63.// F_EK2 = F_EK1 ;
64. EkP1 = (int16)(CuValue - SetValue) ;//偏差=设定-当前
65.
66. //dwTmp1 = (KA*EkP1)/KP1 ; //P
67. //dwTmp1 = (KA*EkP1 - KB*EkP2)/KP1 ; //
68. dwTmp1 = (KA*EkP1 - KB*EkP2 + KC*EkP3)/KP1 ;
69.
70. if(dwTmp1 >= MAX_PID_VALUE_Z)
71. {
72. SumP13 = MAX_PID_VALUE_Z ;
73. }
74. else if(dwTmp1 <= MAX_PID_VALUE_F)
75. {
76. SumP13 = MAX_PID_VALUE_F ;
77. }
78. else
79. {
80. SumP13 = (int16)dwTmp1 ;
81. }
82.
83. if(SumP13 < AEKF)//功率减
84. {
85. wTmp1 = (uint16)(wDATA_F_SWITCH_Z(SumP13)) ;
86.
87. if(Power >= wTmp1)
88. {
89. Power -= wTmp1 ;
90. if(Power < MIN_ROP) //最小功率限制
91. {
92. Power = MIN_ROP ;
93. }
94. }
95. else
96. {
97. Power = MIN_ROP ;
98. }
99. }
100. else if(SumP13 <= AEKZ)
101. {
102. //偏差在此范围内不进行调节
103. }
104. else //(SumP13 > AEKZ) 和大于0 功率加
105. {
106. wTmp1 = SumP13 + Power ;
107.
108. if(wTmp1 >= MAX_ROP)//最大功率限制
109. {
110. wTmp1 = MAX_ROP ;
111. }
112.
113. Power = wTmp1 ;
114. }
115.
116. return Power ; //返回功率值
117.}
118.
119.
120.
121.//---应用实例----
122.//*************************************
123.// 函数名称:
CmdPidFct
124.// 函数功能:
PID控制
125.// 入口参数:
无
126.// 出口参数:
无
127.// 进行PID运算
128.//***************************************
129.void CmdPidFct(void)
130.{
131. static uint8 Tcon = 0 ;
132.
133. Tcon ++ ;
134. if(Tcon >= PIDCYC)//PIDCYC 20MS
135. {
136. Tcon = 0 ;
137. CuRate = T_Cyc>>2 ; //把采样值除4
138. //R_SetPwm = RumMotorPid(R_SetPwm,SetRate,CuRate) ;
139. R_CurPwm = RumMotorPid(R_CurPwm,SetRate,CuRate) ;
140. // R_CurPwm = 100 ;
141. }
142.
143.}
144.
145.阻容降压电源中降低静态功耗的经典电路图
146.分类:
单片机应用 电路应用2013-08-1709:
37 184人阅读 评论(0) 收藏 举报
147.电路图阻容降压静态功耗
148.
一、本方案适用场合
1、低成本电源方案-阻容降压电源
2、驱动一路12V或24V继电器
3、要求静态功耗低,可做到低于0.7W静态功耗
149.电路1如下:
150.
151.继电器驱动电路2如下:
152.
153.二、电路解析
本电源电路可分为两部分,一部是正半波回路,另一部分是负半波回路。
1、先来看正半波回路,此回路通过一个12V稳压管ZD1,12V稳压管后面还有个
78L05(U1),由此就得到了两个电源:
12V与5V
这里的12V通常不用,而5V拿来给MCU供电,外加一些LED、蜂鸣器驱动等
154.2、再来看负半波回路,此回路也通过一个12V的稳压管ZD2,但关键点是在此12V
稳压管的旁边并联了一个三极管Q1,这个Q1就是这个电路中最大的亮点,来
看看:
我们可通过MCU控制P_HT这个IO口
P_HT=0时,三极管Q2导通,从而使得Q1导通,当Q1导通时,稳压管ZD2被三极管
的CE极短路,最终ZD2在这时就没有起到稳压的作用,VCC的电压为接近12V
P_HT=1时,三极管Q2不导通,从而Q1也没有导通,这时稳压管ZD2起到了稳压的
作用,这时候VCC相对12V来讲有12V的电压,这个电压刚好可用作继电器的驱动。
最终我们就可通过控制P_HT来控制驱动继电器,当控制器刚上电机,关掉负半波
的回路,也就是继电器断开的状态,这时负半波是直接被三极管Q1所短路的,那么这
里ZD2就没有功耗的产生,从而降低也静功耗。
155. 此电路图实属巧妙,为我司众多产品做出了巨大的贡献。
用定时中断来接收红外遥控信号
分类:
单片机应用2013-07-2408:
28 247人阅读 评论(0) 收藏 举报
用定时中断来接收红外遥控信号
[cpp] viewplaincopy
1.//====红外接收相关定义=============================
2.#define IrDatHigh (P_IrRec == 1) //接收数据高
3.#define IrDatLow (P_IrRec == 0) //接收数据低
4.#define Ir_EdgeDown ((RStatus_IR&0x03) == 0x02)//IR下降沿 1--0
5.#define Ir_EdgeUp ((RStatus_IR&0x03) == 0x01) //IR上升沿 0--1
6.
7.//红外数据长度 N个字节 可自定义
8.#define IrDatLong (uint8)20
9.
10.//--------------起始
11.#define TST_LOW (uint8)107 //起始低脉宽 5.35MS
12.#define TST_LOW_L (TST_LOW - 20) //起始低判断范围
13.#define TST_LOW_H (TST_LOW + 20) //12
14.#define TST_HIGH (uint8)145 //起始高脉宽 7.25MS
15.#define TST_HIGH_L (TST_HIGH - 20) //起始高判断范围
16.#define TST_HIGH_H (TST_HIGH + 20) //
17.//---------------数据
18.#define TDAT_LOW (uint8)28 //数据低脉宽 1.4MS
19.#define TDAT_LOW_L (TDAT_LOW - 19) //数据
20.#define TDAT_LOW_H (TDAT_LOW + 19) //10
21.#define TDAT_HIGH (uint8)66 //数据高脉宽 3.3MS
22.#define TDAT_HIGH_L (TDAT_HIGH - 19) //数据
23.#define TDAT_HIGH_H (TDAT_HIGH + 19) //
24.
25.
26.
27.void interrupt ser(void)//中断服务程序
28.{
29. static uint8 PIR = 0 ;
30. static uint8 RStatus_IR = 0 ;
31. static uint8 ByteNum=0,BitNum=0;
32.
33. TIM6_SR1 = 0x00; // 清除更新标志 50u 中断一 次
34.
35.
36. TconIr ++ ; //脉冲计数
37. if(TconIr == 0) //溢出
38. {
39. RMIR = MIR_RST ; //退出接收状态
40. }
41.
42. PIR <<= 1 ;
43. if(IrDatHigh) //读IR接收管脚的状态
44. {
45. PIR |= 0x01 ;
46. }
47.
48. //对接收管脚的数据进行滤波处理
49. RStatus_IR <<= 1 ;
50. if((PIR & 0x07) == 0x07)//111
51. {
52. RStatus_IR |= 0X01 ;
53. }
54. else if((PIR & 0x07) == 0X00)//000
55. {
56. RStatus_IR &= ~0X01 ;
57. }
58. else
59. {
60. if(RStatus_IR & 0x02)RStatus_IR |= 0x01 ;
61. }
62.
63.
64. if(F_IrRecOk) return ; //数据未取出 不再接收数据
65.
66. //--上升沿或下降沿到来-------------
67. if(Ir_EdgeDown || Ir_EdgeUp)
68. {
69. //-------1111--空闲--------------------
70. if(RMIR == MIR_RST) //
71. {
72. if(Ir_EdgeUp)
73. {
74. RMIR = MIR_RST ; //退出接收状态
75. }
76. else //起始接收下降沿
77. {
78. TconIr = 0 ;
79. RMIR = MIR_P1 ;//接收起始
80. F_IrStatus = 0 ;// 接收起始低
81. }
82. }
83. //----22222--接收起始码-----------------
84. else if(RMIR == MIR_P1)//
85. {
86. if(!
F_IrStatus)//起始状态0 只接收上升沿
87. {
88. if(Ir_EdgeUp)
89. { //接收起始码低电平脉宽
90. if((TconIr >= TST_LOW_L) && (TconIr <= TST_LOW_H))
91. {
92. F_IrStatus = 1 ; //起始低验证成功
93. TconIr = 0 ;
94. }
95. else
96. {
97. RMIR = MIR_RST ; //退出接收状态
98. }
99. }
100. }
101. else //if(F_IrStatus)//起始状态1 只收下升沿
102. {
103. if(Ir_EdgeDown)
104. {//接收起始码高电平脉宽
105. if((TconIr >= TST_HIGH_L) && (TconIr <= TST_HIGH_H))
106. {
107. RMIR = MIR_P2 ; //起始高验证成功
108. TconIr = 0 ;
109. ByteNum = 0;
110. BitNum = 0;
111. }
112. else
113. {
114. RMIR = MIR_RST ; //退出接收状态
115. }
116. }
117. }
118. }
119. //----33333--接收数据码--------------
120. else if(RMIR == MIR_P2) //
121. {
122. if(Ir_EdgeUp)//滤过低电平
123. {
124. TconIr = 0 ;
125. return ;
126. }
127. else //if()
128. { //接收到数据低
129. if((TconIr >= TDAT_LOW_L)&&(TconIr <= TDAT_LOW_H))
130. {
131. IrDatRce[ByteNum] &= ~(1<132. }//接收到数据高
133. else//if((TconIr >= TDAT_LOW_L) && (TconIr <= TDAT_LOW_H))
134. {
135. IrDatRce[ByteNum] |= (1<136. }
137