燕山大学暑期校内实习stm8h程序集合_第1页
燕山大学暑期校内实习stm8h程序集合_第2页
燕山大学暑期校内实习stm8h程序集合_第3页
燕山大学暑期校内实习stm8h程序集合_第4页
燕山大学暑期校内实习stm8h程序集合_第5页
已阅读5页,还剩62页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、l 燕山大学暑期校内实习程序合集1 一个小灯亮灭#include"stm8s.h"void main(void) GPIO_DeInit( GPIOD);/恢复指定端口 GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_PP_LOW_SLOW);while(1) GPIO_WriteLow( GPIOD, GPIO_PIN_0 );/*PD0口输出低电平*/2 小灯闪烁#include"stm8s.h"/头文件void delay(u32 i)/*延时子程序*/ u32 j; for(j=0;j<i;j+) ;v

2、oid main(void)/主程序头 GPIO_DeInit( GPIOD);/选pd口 GPIO_Init(GPIOD, GPIO_PIN_LNIB, GPIO_MODE_OUT_PP_LOW_SLOW);/低4位低电平0亮while(1)/死循环 GPIO_WriteLow( GPIOD, GPIO_PIN_LNIB );/*PD0口输出低电平灯亮*/ delay(20000);/延时 GPIO_WriteHigh( GPIOD, GPIO_PIN_LNIB );/输出高电平灯灭 delay(5000);/延时3 左移流水灯 #include"stm8s.h"/头文件

3、void delay(u32 i)/*延时子程序*/ u32 j; for(j=0;j<i;j+) ;void main(void)/主程序头 GPIO_DeInit(GPIOD);/初始化pd口 GPIO_Init(GPIOD, GPIO_PIN_LNIB, GPIO_MODE_OUT_PP_LOW_SLOW);/低4位低电平0亮 while(1)/大循环 u8 n=0xfe;/付初值1111 1110 for(int m=0;m<4;m+) GPIO_Write(GPIOD,n);/翻转 delay(5000);/延时 n=n<<1;/左移 n=n+1;/灭前一个灯

4、 4 数组流水灯#include"stm8s.h"/头文件void delay(u32 i)/*延时子程序*/ u32 j; for(j=0;j<i;j+) ;void main(void)/主程序头 GPIO_DeInit(GPIOD);/初始化pd口 GPIO_Init(GPIOD, GPIO_PIN_LNIB, GPIO_MODE_OUT_PP_LOW_SLOW);/低4位低电平0亮 unsigned char num4=0xfe,0xfd,0xfb,0xf7;while(1)/循环 for(int i=0;i<4;i+) GPIO_Write(GPIOD

5、,numi);/分别给高4位和低4位PD口赋值 delay(50000);/延时 5 小灯变频闪烁#include"stm8s.h"/头文件void delay(u32 i)/*延时子程序*/ u32 j; for(j=0;j<i;j+) ;void main(void)/主程序头 GPIO_DeInit( GPIOD);/初始化pd口 GPIO_Init(GPIOD, GPIO_PIN_LNIB, GPIO_MODE_OUT_PP_LOW_SLOW);/低4位低电平0亮 while(1)/大循环 int x=10; for(int y=0;y<x;y+) GP

6、IO_WriteReverse( GPIOD, GPIO_PIN_LNIB );/翻转灯亮灭 delay(50000);/延时 int m=10; for(int n=0;n<m;n+) GPIO_WriteReverse( GPIOD, GPIO_PIN_LNIB );/翻转灯亮灭 delay(5000);/延时6 查询法TIM2精确控制小灯闪烁/小灯闪烁#include"stm8s.h"/头void delay_ms(u16 i) TIM2_DeInit(); TIM2_TimeBaseInit(TIM2_PRESCALER_2,1000); while(i-)

7、TIM2_Cmd(ENABLE); while(TIM2_GetFlagStatus(TIM2_FLAG_UPDATE)!=1); TIM2_ClearFlag(TIM2_FLAG_UPDATE); TIM2_Cmd(DISABLE);void main(void)/主程序头 GPIO_DeInit( GPIOD);/选pd口 GPIO_Init(GPIOD, GPIO_PIN_LNIB, GPIO_MODE_OUT_PP_LOW_SLOW);/灯亮 while(1)/死循环 GPIO_WriteReverse(GPIOD, GPIO_PIN_LNIB);/灯翻转亮灭 delay_ms(500

8、);/延时 7 TIM2精确控制流水灯(查询法) /改变小灯闪烁频率#include"stm8s.h"/头 void delay_ms(u16 i) TIM2_DeInit(); TIM2_TimeBaseInit(TIM2_PRESCALER_2,1000); while(i-) TIM2_Cmd(ENABLE); while(TIM2_GetFlagStatus(TIM2_FLAG_UPDATE)!=1); TIM2_ClearFlag(TIM2_FLAG_UPDATE); TIM2_Cmd(DISABLE);void main(void)/主程序头 GPIO_DeIn

9、it( GPIOD);/选pd口 GPIO_Init(GPIOD, GPIO_PIN_LNIB, GPIO_MODE_OUT_OD_LOW_SLOW); while(1)/死循环 u8 n=0xfe; for (int i=0;i<4;i+) GPIO_Write(GPIOD, n); delay_ms(500); n=n<<1; n=n+1; 8 TIM2实现精确延时流水灯 #include"stm8s.h"/void delay_ms(u16 i) TIM2_DeInit(); TIM2_TimeBaseInit(TIM2_PRESCALER_2,10

10、00); while(i-) TIM2_Cmd(ENABLE); while(TIM2_GetFlagStatus(TIM2_FLAG_UPDATE)!=1); TIM2_ClearFlag(TIM2_FLAG_UPDATE); TIM2_Cmd(DISABLE);void main(void)/主程序头 u8 n; GPIO_DeInit( GPIOD);/选pd口 GPIO_Init(GPIOD, GPIO_PIN_LNIB, GPIO_MODE_OUT_OD_LOW_SLOW); while(1)/死循环 n=0xfe; for (int i=0;i<4;i+) GPIO_Writ

11、e(GPIOD, n); delay_ms(500); n=n<<1; n=n+1; 9 TIM2控制灯亮灭(中断)#include"stm8s.h"u16 i=0;/*定时器2的配置*/void TIM2_Configuration(void) TIM2_DeInit(); /TIM2初始化 TIM2_TimeBaseInit(TIM2_PRESCALER_2, 2000);/预分频2,计数值2000,即2ms TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);/更新模式,开中断 TIM2_Cmd(ENABLE);/开启TIM2 en

12、ableInterrupts(); /开总中断/*IO口初始化*/void GPIO_Configuration(void) GPIO_DeInit(GPIOB); GPIO_Init(GPIOB, GPIO_PIN_LNIB, GPIO_MODE_OUT_PP_LOW_FAST); void main() /主函数 TIM2_Configuration(); GPIO_Configuration(); while(1); #pragma vector =15/TIM2中断入口_interrupt void TIMER2_IRQHander(void) i+; if(i=250) GPIO_W

13、riteReverse(GPIOB, GPIO_PIN_LNIB); i=0; TIM2_ClearITPendingBit(TIM2_IT_UPDATE);10 中断控制按键实现小灯变频#include"stm8s.h"void delay_ms(u16 i);u8 t=1;/*引脚配置*/void GPIO_configurating(void) GPIO_DeInit(GPIOB); GPIO_Init(GPIOB, GPIO_PIN_0, GPIO_MODE_IN_PU_IT );GPIO_DeInit(GPIOD);GPIO_Init(GPIOD,GPIO_PIN

14、_LNIB, GPIO_MODE_OUT_PP_HIGH_FAST);/*定时器配置*/void exit()EXTI_DeInit();EXTI_SetExtIntSensitivity( EXTI_PORT_GPIOB, EXTI_SENSITIVITY_RISE_ONLY);/配置中断模式enableInterrupts();/开总中断void main() CLK_DeInit();exit(); GPIO_configurating(); while(1) if(t=1) GPIO_WriteReverse(GPIOD, GPIO_PIN_0); delay_ms(250); if(

15、t=2) GPIO_WriteReverse(GPIOD, GPIO_PIN_0); delay_ms(500); if(t=3) GPIO_WriteReverse(GPIOD, GPIO_PIN_0); delay_ms(1000); if(t>3) t=1; #pragma vector=6_interrupt void Exit_portb_irqhander(void) t=t+1; while(!(GPIO_ReadInputPin(GPIOB, GPIO_PIN_0) );/循环执行void delay_ms(u16 i)/精确定时TIM2_DeInit();TIM2_Ti

16、meBaseInit(TIM2_PRESCALER_2, 1000);/1ms while(i-) TIM2_Cmd(ENABLE); while( TIM2_GetFlagStatus(TIM2_FLAG_UPDATE)!=1); TIM2_ClearFlag( TIM2_FLAG_UPDATE); TIM2_Cmd(DISABLE); 11 时钟分频#include"stm8s.h"void delay(u32 i);/函数声明void main()/函数入口 CLK_DeInit(); GPIO_DeInit(GPIOD);/PD口置位 GPIO_Init(GPIOD

17、, GPIO_PIN_LNIB, GPIO_MODE_OUT_OD_LOW_SLOW); /*PD口初始化,PD口的低四位,模式为开漏输出,低电平,慢速*/ while(1) CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV8 ); int k=5; int m; for(m=0;m<k;m+) GPIO_WriteLow(GPIOD, GPIO_PIN_LNIB );/PD的低四位置0 delay(10000);/延时 GPIO_WriteHigh(GPIOD, GPIO_PIN_LNIB);/PD的低四位置1 delay(10000);/延时 C

18、LK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV2 ); int i=5; int j; for(j=0;j<i;j+) GPIO_WriteLow(GPIOD, GPIO_PIN_LNIB );/PD的低四位置0 delay(10000);/延时 GPIO_WriteHigh(GPIOD, GPIO_PIN_LNIB);/PD的低四位置1 delay(10000);/延时 void delay(u32 i)/延时子程序 u32 j; for(j=0;j<i;j+) ;12 查询法控制按键#include<stm8s.h>void d

19、elay(u32 s);void main(void) GPIO_DeInit(GPIOB); GPIO_Init(GPIOB, GPIO_PIN_0, GPIO_MODE_OUT_PP_HIGH_FAST);/初始化端口,包括端口B引脚0 GPIO_Init(GPIOB, GPIO_PIN_1,GPIO_MODE_IN_PU_NO_IT);/初始化端口,包括端口B引脚1 while(1) if(!(GPIO_ReadInputPin(GPIOB, GPIO_PIN_1) delay(10); /去抖 if(!(GPIO_ReadInputPin(GPIOB, GPIO_PIN_1)/松手检测

20、 GPIO_WriteReverse(GPIOB, GPIO_PIN_0); while( !(GPIO_ReadInputPin(GPIOB, GPIO_PIN_1) );/检验按键是否结束 void delay(u32 s)/延时子程序 u32 i,j; for(i=s;i>0;i-) for(j=110;j>0;j-);13 按键改变小灯闪烁变频(查询法)/*按键改变小灯闪烁频率*/#include "stm8s.h"#define uint unsigned int#define uchar unsigned charuint i=0;void GPIO

21、_INIT();void Delay(uint del);uchar key();void main() GPIO_INIT(); while(1) key(); switch(i) case 0: GPIO_WriteLow(GPIOD, GPIO_PIN_0);/第0位给0 GPIO_WriteHigh(GPIOD, GPIO_PIN_1); GPIO_WriteHigh(GPIOD, GPIO_PIN_2); GPIO_WriteHigh(GPIOD, GPIO_PIN_3); break; case 1: GPIO_WriteLow(GPIOD, GPIO_PIN_1);/第1位给0

22、GPIO_WriteHigh(GPIOD, GPIO_PIN_0); GPIO_WriteHigh(GPIOD, GPIO_PIN_2); GPIO_WriteHigh(GPIOD, GPIO_PIN_3); break; case 2: GPIO_WriteLow(GPIOD, GPIO_PIN_2);/第2位给0 GPIO_WriteHigh(GPIOD, GPIO_PIN_0); GPIO_WriteHigh(GPIOD, GPIO_PIN_1); GPIO_WriteHigh(GPIOD, GPIO_PIN_3); break; case 3: GPIO_WriteLow(GPIOD,

23、 GPIO_PIN_3);/第3位给0 GPIO_WriteHigh(GPIOD, GPIO_PIN_0); GPIO_WriteHigh(GPIOD, GPIO_PIN_1); GPIO_WriteHigh(GPIOD, GPIO_PIN_2); break; void GPIO_INIT()/初始化端口D GPIO_DeInit(GPIOD); GPIO_Init(GPIOD,GPIO_PIN_ALL, GPIO_MODE_OUT_PP_LOW_FAST); GPIO_Init(GPIOB,GPIO_PIN_1, GPIO_MODE_IN_PU_NO_IT );void Delay(uin

24、t del)/延时10ms uint i1,j; for(i1=0; i1<del; i1+) for(j=0; j<1827; j+);uchar key() if(!(GPIO_ReadInputPin( GPIOB, GPIO_PIN_1) ) Delay(2); /20毫秒软件防抖 if(!(GPIO_ReadInputPin( GPIOB, GPIO_PIN_1) i+; if(i=4) i=0; Delay(100); return i;14 按键实现流水灯的控制#include "stm8s.h"#define uint unsigned int#

25、define uchar unsigned charuint i=0;void GPIO_INIT();void Delay(uint del);uchar key();void main() GPIO_INIT(); while(1) key(); switch(i) case 0: GPIO_WriteHigh(GPIOD, GPIO_PIN_LNIB);/4口全给1 break; case 1: GPIO_Write(GPIOD, 0xfe);/PD0口给0 break; case 2: GPIO_Write(GPIOD, 0xfd); break; case 3: GPIO_Write

26、(GPIOD, 0xfb); break; case 4: GPIO_Write(GPIOD, 0xf7); break; case 5: GPIO_WriteLow(GPIOD, GPIO_PIN_LNIB); break; void GPIO_INIT()/初始化端口D GPIO_DeInit(GPIOD); GPIO_Init(GPIOD,GPIO_PIN_ALL, GPIO_MODE_OUT_PP_LOW_FAST); GPIO_Init(GPIOB,GPIO_PIN_1, GPIO_MODE_IN_PU_NO_IT );void Delay(uint del)/延时10ms uint

27、 i1,j; for(i1=0; i1<del; i1+) for(j=0; j<1827; j+);uchar key() if(!(GPIO_ReadInputPin( GPIOB, GPIO_PIN_1) ) Delay(10); /20毫秒软件防抖 if(!(GPIO_ReadInputPin( GPIOB, GPIO_PIN_1) i+; if(i=6) i=0; Delay(200); return i;15 按键实现灯亮 ,闪,停,流水/*查询 按键改变小灯频率*/#include "stm8s.h" #define uint unsigned i

28、nt#define uchar unsigned charuint i=0;void GPIO_INIT();/初始化void Delay(uint del);/延时声明uchar key(); u8 m=0xfe; u8 n=0; void main()/主函数入口 GPIO_INIT();/调用函数 while(1)/大循环 key(); switch(i) case 0: GPIO_WriteLow(GPIOD, GPIO_PIN_LNIB); break; /*流水灯*/ case 1: if(n<4) GPIO_Write(GPIOD,m);/翻转 Delay(50);/延时

29、m=m<<1;/左移 m=m+1;/灭前一个灯 n+; else n=0;m=0xfe; break; case 3: GPIO_WriteReverse(GPIOD, GPIO_PIN_LNIB);/PD1端口给0 Delay(50); break; case 2: GPIO_WriteHigh(GPIOD, GPIO_PIN_LNIB);/4口全给1 break; void GPIO_INIT()/初始化端口D GPIO_DeInit(GPIOD); GPIO_Init(GPIOD,GPIO_PIN_ALL, GPIO_MODE_OUT_PP_LOW_FAST); GPIO_I

30、nit(GPIOB,GPIO_PIN_1, GPIO_MODE_IN_PU_NO_IT );void Delay(uint del)/延时10ms uint i1,j; for(i1=0; i1<del; i1+) for(j=0; j<1870; j+); uchar key() if(!(GPIO_ReadInputPin( GPIOB, GPIO_PIN_1) ) Delay(10); /防抖 if(!(GPIO_ReadInputPin( GPIOB, GPIO_PIN_1) i+; if(i=4) i=0; Delay(100); return i; 16 定时器捕获按键

31、控制小灯亮灭#include"stm8s.h"void delay_ms(u16 i);u8 t=0;/*引脚配置*/void TIM2_configuration(void) TIM2_DeInit();/恢复TIM2寄存器到默认值 TIM2_ICInit(TIM2_CHANNEL_1 ,/扑捉通道 TIM2_ICPOLARITY_RISING, /扑捉极性 TIM2_ICSELECTION_DIRECTTI,/扑捉输入脚 TIM2_ICPSC_DIV1,/扑捉预分频 0x00);/滤波频率 TIM2_ITConfig(TIM2_IT_CC1, ENABLE);/设置TI

32、M2中断,扑捉比较1通道 TIM2_CCxCmd(TIM2_CHANNEL_1, ENABLE);/开TIM2的1通道使能 TIM2_Cmd(ENABLE);/开启TIM2使能 enableInterrupts(); xvoid GPIO_configuration(void)/初始化端口GPIO_DeInit(GPIOB);GPIO_Init(GPIOB, GPIO_PIN_LNIB, GPIO_MODE_OUT_PP_HIGH_FAST);void main()/主函数入口 CLK_DeInit();GPIO_configuration();TIM2_configuration(); wh

33、ile(1) ; /*中断*/#pragma vector=16/捕获比较中断入口_interrupt void Exit_portb_irqhander(void)GPIO_WriteReverse(GPIOB, GPIO_PIN_LNIB);TIM2_ClearITPendingBit( TIM2_IT_CC1 );/清TIM2捕获比较中断标志位17 TIM2输入捕获按键控制呼吸灯变化(输出比较实现)#include"stm8s.h"int i=0;void TIM2_Configuration(void);void delay(u32 i);/*主程序*/void m

34、ain() TIM2_Configuration(); /enableInterrupts(); while(1) if(i=0) for(u16 x=0;x<500;x+)TIM2_SetCompare1(x);delay(200); for(u16 x=0;x>500;x-)TIM2_SetCompare1(x);delay(200); if (i=1) for(u16 x=0;x<500;x+)TIM2_SetCompare1(x);delay(50); for(u16 x=500;x>0;x-)TIM2_SetCompare1(x);delay(50);if(i

35、=2) i=0; /*中断*/#pragma vector=16_interrupt void Exit_portb_irqhander(void)i=i+1;if(i=2)i=0;TIM2_ClearITPendingBit( TIM2_IT_CC2 );void TIM2_Configuration(void) TIM2_DeInit(); /TIM2初始化 TIM2_TimeBaseInit(TIM2_PRESCALER_2, 300);/预分频2,计数值1000,即1ms TIM2_OC1Init( TIM2_OCMODE_PWM1 , TIM2_OUTPUTSTATE_ENABLE,

36、 0, TIM2_OCPOLARITY_HIGH); TIM2_ICInit(TIM2_CHANNEL_2 , TIM2_ICPOLARITY_RISING, TIM2_ICSELECTION_DIRECTTI, TIM2_ICPSC_DIV1, 0x00); TIM2_ITConfig(TIM2_IT_CC2, ENABLE); TIM2_CCxCmd(TIM2_CHANNEL_2, ENABLE); TIM2_Cmd(ENABLE); enableInterrupts();void delay(u32 i)u32 j;for( j=0;j<i;j+);/延时程序18 ADC1采集电压

37、值控制灯亮灭/*ADC1的配置*/#include"stm8s.h"int i;void ADC_Configuration() ADC1_DeInit(); ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS,/连续转换模式 ADC1_CHANNEL_1, /通道1 ADC1_PRESSEL_FCPU_D2,/ADC时钟2分频 ADC1_EXTTRIG_GPIO,DISABLE,/GPIO外部触发关闭 ADC1_ALIGN_RIGHT,/结果右对齐 ADC1_SCHMITTTRIG_CHANNEL1,DISABLE);/关闭通道1的施密特触发

38、 ADC1_ITConfig(ADC1_IT_EOCIE,ENABLE);/设置转换结果中断 ADC1_Cmd(ENABLE); ADC1_StartConversion();/自动转换 void main()/主函数入口 GPIO_DeInit(GPIOD);/初始化PD口 GPIO_Init(GPIOD, GPIO_PIN_LNIB, GPIO_MODE_OUT_PP_HIGH_FAST); ADC_Configuration(); while(1) i=ADC1_GetConversionValue(); if(i<=500) GPIO_WriteHigh(GPIOD, GPIO_

39、PIN_LNIB); delay(100) void delay(u32 i)/*延时子程序*/ u32 j; for(j=0;j<i;j+) ; 19 ADC1采集实现灯变频闪/*ADC1的配置*/#include"stm8s.h" void delay(u32 i)/*延时子程序*/ u32 j; for(j=0;j<i;j+) ;int i;void ADC_Configuration() ADC1_DeInit(); ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS,/连续转换模式 ADC1_CHANNEL_1, /通道1

40、 ADC1_PRESSEL_FCPU_D2,/ADC时钟2分频 ADC1_EXTTRIG_GPIO,DISABLE,/GPIO外部触发关闭 ADC1_ALIGN_RIGHT,/结果右对齐 ADC1_SCHMITTTRIG_CHANNEL1,DISABLE);/关闭通道1的施密特触发 ADC1_ITConfig(ADC1_IT_EOCIE,ENABLE);/设置转换结果中断 ADC1_Cmd(ENABLE); ADC1_StartConversion();/自动转换 void main()/主函数入口 GPIO_DeInit(GPIOD);/初始化PD口 GPIO_Init(GPIOD, GPI

41、O_PIN_LNIB, GPIO_MODE_OUT_PP_HIGH_FAST); ADC_Configuration(); while(1) i=ADC1_GetConversionValue(); if(i>500) GPIO_WriteReverse(GPIOD, GPIO_PIN_LNIB); delay(1000); else GPIO_WriteReverse(GPIOD, GPIO_PIN_LNIB); delay(5000); 20 ADC1采集控制灯亮度/*ADC1的配置*/#include"stm8s.h"int i;u32 x; void dela

42、y(u32 i)/*延时子程序*/ u32 j; for(j=0;j<i;j+) ;void ADC_Configuration() ADC1_DeInit(); ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS,/连续转换模式 ADC1_CHANNEL_1, /通道1 ADC1_PRESSEL_FCPU_D2,/ADC时钟2分频 ADC1_EXTTRIG_GPIO,DISABLE,/GPIO外部触发关闭 ADC1_ALIGN_RIGHT,/结果右对齐 ADC1_SCHMITTTRIG_CHANNEL1,DISABLE);/关闭通道1的施密特触发 ADC1_ITConfig(ADC1_IT_EOCIE,ENABLE);/设置转换结果中断 ADC1_Cmd(ENABLE); ADC1_StartConversion();/自动转换void oc_cont(void) TIM2_DeInit();/TIM2初始化 TIM2_TimeBaseInit(TIM2_PRESCALER_2,300); TIM2_OC1Init(TIM2_OCMO

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论