HT325232合泰杯单片机应用设计资料(合泰杯针对于32位,八位也可一起讨论)
一、时间安排与经历
时间线 | 计划任务情况 | 实际完成情况 |
---|---|---|
1月25前 | 完成任务书 | 完成 |
2月31前 | 完成电路设计 | 30% |
3月25前 | 完成机械结构设计 | 50% |
4月15前 | 完成嵌入式程序 | 0% |
5月1前 | 完成外观设计(23年还有外观设计奖) | 0% |
赛前15天 | 完成之前所有任务 | 1000% |
其实每一个大学生在校会有各种各样的活动,团建,比赛,项目,课程作业,考试甚至是男女朋友,家人的各种牵绊。最终很难落实任务,但是并不说明提前准备是没有用的,在零碎时间中我会抽出时间去整理和测试单片机的各种外设功能,在有一定基础上大概累计一周时间完成对于32位机的总体认识。最后在接近两周时间集中完成整个项目。这是针对于我个人的情况。在此会分享一些关于PCB制作,路演经验一级HT3252352自己研究的嵌入式程序逻辑和demo方便大家快速搭建好属于自己的项目,顺利完赛。
二、参考资料网站
首先是一些非常好用的网站资料。
三、自己写的部分超好用代码
- 点亮led
void led_init(void)
{
//使能PC端口的时钟
CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
CKCUClock.Bit.PC = 1;
CKCUClock.Bit.AFIO = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE);
//配置端口功能为GPIO
AFIO_GPxConfig(GPIO_PC, GPIO_PIN_15, AFIO_FUN_GPIO);
AFIO_GPxConfig(GPIO_PC, GPIO_PIN_14, AFIO_FUN_GPIO);
//配置IO口为输出模式
GPIO_DirectionConfig(HT_GPIOC, GPIO_PIN_15, GPIO_DIR_OUT);
GPIO_DirectionConfig(HT_GPIOC, GPIO_PIN_14, GPIO_DIR_OUT);
//默认输出1
GPIO_WriteOutBits(HT_GPIOC, GPIO_PIN_15, SET);
GPIO_WriteOutBits(HT_GPIOC, GPIO_PIN_14, SET);
}
- 延时函数
//mS微秒级延时程序
void delay_us(u32 us)
{
u32 i;
SYSTICK_ClockSourceConfig(SYSTICK_SRC_STCLK); //选择外部参考时钟作为SysTick时钟源。8MHZ
SYSTICK_SetReloadValue(SystemCoreClock / 8 / 1000000); // 重装计数初值
SYSTICK_IntConfig(DISABLE); // 是否开启中断
SYSTICK_CounterCmd(SYSTICK_COUNTER_CLEAR); //清空定时器
SYSTICK_CounterCmd(SYSTICK_COUNTER_ENABLE); //使能
for( i = 0;i < us;i++ )
{
while( !( (SysTick->CTRL) & (1<<16) ) );
}
SYSTICK_CounterCmd(SYSTICK_COUNTER_DISABLE); //关闭
SYSTICK_CounterCmd(SYSTICK_COUNTER_CLEAR); //复位清零
}
- 配置usart串口收发
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
{
CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
CKCUClock.Bit.AFIO = 1;
CKCUClock.Bit.PA = 1;
CKCUClock.Bit.USART1 = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE);
}
{
CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
CKCUClock.Bit.AFIO = 1;
CKCUClock.Bit.PA = 1;
CKCUClock.Bit.USART0 = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE);
}
GPIO_PullResistorConfig(HT_GPIOA, GPIO_PIN_5, GPIO_PR_UP);
GPIO_PullResistorConfig(HT_GPIOA, GPIO_PIN_3, GPIO_PR_UP);
AFIO_GPxConfig(GPIO_PA, AFIO_PIN_4, AFIO_FUN_USART_UART);
AFIO_GPxConfig(GPIO_PA, AFIO_PIN_5, AFIO_FUN_USART_UART);
AFIO_GPxConfig(GPIO_PA, AFIO_PIN_2, AFIO_FUN_USART_UART);
AFIO_GPxConfig(GPIO_PA, AFIO_PIN_3, AFIO_FUN_USART_UART);
/*
波特率: 115200
长度: 8bits
停止位: 1位
校验位: 无
模式: 正常模式
*/
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WORDLENGTH_8B;
USART_InitStructure.USART_StopBits = USART_STOPBITS_1;
USART_InitStructure.USART_Parity = USART_PARITY_NO;
USART_InitStructure.USART_Mode = USART_MODE_NORMAL;
USART_Init(HT_USART1, &USART_InitStructure);
USART_Init(HT_USART0, &USART_InitStructure);
//中断设置
NVIC_EnableIRQ(USART1_IRQn);
NVIC_EnableIRQ(USART0_IRQn);
USART_IntConfig(HT_USART1, USART_INT_RXDR, ENABLE);
USART_IntConfig(HT_USART0, USART_INT_RXDR, ENABLE);
// 使能 COM1_PORT 发送和接收
USART_TxCmd(HT_USART1, ENABLE);
USART_RxCmd(HT_USART1, ENABLE);
USART_TxCmd(HT_USART0, ENABLE);
USART_RxCmd(HT_USART0, ENABLE);
// USART_RXTLConfig(COM1_PORT, USART_RXTL_04); 设置FIFO接收等级
}
/****实现函数
函数说明:接收中断服务函数
*/
void USART1_IRQHandler(void) //串口1中断
{
if( USART_GetFlagStatus(HT_USART1, USART_FLAG_RXDR ) ) //接收中断
{
// data = USART_ReceiveData(HT_USART1); //读取接收到的数据
// printf("data = %c\n",data);
data1 = USART_ReceiveData(HT_USART1); //读取接收到的数据
Usart_Sendbyte(HT_USART1,data1);
//把收到的数据发送回电脑
} //发送多字节会多次进入中断
USART_ClearFlag(HT_USART1,USART_FLAG_RXDR);
}
void USART0_IRQHandler(void) //串口0中断
{
if( USART_GetFlagStatus(HT_USART0, USART_FLAG_RXDR ) ) //接收中断
{
data2 = USART_ReceiveData(HT_USART0); //读取接收到的数据
Usart_Sendbyte(HT_USART0,data2); //把收到的数据发送回电脑
} //发送多字节会多次进入中断
USART_ClearFlag(HT_USART0,USART_FLAG_RXDR);
}
void USART_Tx1(const char* TxBuffer, u32 length)
{
int i;
for (i = 0; i < length; i++)
{
while (!USART_GetFlagStatus(HT_USART1, USART_FLAG_TXC));
USART_SendData(HT_USART1, TxBuffer[i]);
}
}
void USART_Tx0(const char* TxBuffer, u32 length)
{
int i;
for (i = 0; i < length; i++)
{
while (!USART_GetFlagStatus(HT_USART0, USART_FLAG_TXC));
USART_SendData(HT_USART0, TxBuffer[i]);
}
}
void Usart_Sendbyte(HT_USART_TypeDef* USARTx, u8 data)
{
USART_SendData(USARTx, data);
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXDE) == RESET);
}
void Usart_SendArray(HT_USART_TypeDef* USARTx, u8 *array,u8 num)
{
u8 i;
for( i = 0;i < num;i++)
{
Usart_Sendbyte(USARTx,*array);
array++;
}
}
void Usart_SendStr(HT_USART_TypeDef* USARTx, uint8_t *str)
{
uint8_t i;
for(i = 0;str[i] != '\0';i++)
{
Usart_Sendbyte(USARTx,str[i]);
}
}
- BFTM中断
void bftm_Init(u32 nus)
{
CKCU_PeripClockConfig_TypeDef CKCUClock = {{ 0 }};
CKCUClock.Bit.BFTM0 = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE);
NVIC_EnableIRQ(BFTM0_IRQn);//使能中断
BFTM_SetCompare(HT_BFTM0, SystemCoreClock/1000000*nus);//设置比较器值
BFTM_SetCounter(HT_BFTM0, 0);
BFTM_IntConfig(HT_BFTM0, ENABLE);
BFTM_EnaCmd(HT_BFTM0, ENABLE);//使能计数器
}
//bftm中断函数a
void BFTM0_IRQHandler(void)
{
OLED_ShowNum1(100,4,a,1,8);
//干你想干的任何事,例如显示一个变量
}
- ADC
void ADC_Configuration(void)
{
CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
//RETARGET_Configuration(); //设定UART配置
//NVIC_EnableIRQ(ADC_IRQn); //使能ADC中断
CKCUClock.Bit.AFIO = 1;
CKCUClock.Bit.ADC = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE);//使能ADC及AFIO时钟
CKCU_SetADCPrescaler(CKCU_ADCPRE_DIV64); //设定ADC工作频率为72/64 MHz = 1.125MHz
AFIO_GPxConfig(GPIO_PA, AFIO_PIN_6, AFIO_MODE_2);//设定ADC接脚
/* Continuous Mode, Length 1, SubLength 1 */
ADC_RegularGroupConfig(HT_ADC, CONTINUOUS_MODE, 1, 1); //设定为连续转换模式,每次一个信道、一笔数据
/* ADC Channel n, Rank 0, Sampling clock is (1.5 + 0) ADCLK
Conversion time = (sampling clock + 12.5) / ADCLK = 12.4 uS */
ADC_RegularChannelConfig(HT_ADC, ADC_CH_6, 0); //设定ADC转换速度
ADC_RegularTrigConfig(HT_ADC, ADC_TRIG_SOFTWARE); //使用软件触发ADC转换
ADC_IntConfig(HT_ADC, ADC_INT_SINGLE_EOC, ENABLE); //使能ADC转换完毕产生中断
}
- 多路PWM
void PWM_Init(void)
{
{ /* Enable peripheral clock */
CKCU_PeripClockConfig_TypeDef CKCUClock = {{ 0 }};
CKCUClock.Bit.GPTM0 = 1;
CKCUClock.Bit.AFIO = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE);
}
/* Configure AFIO mode as TM function */
#if (HTCFG_PWM0_EN == 1)
AFIO_GPxConfig(GPIO_PC, AFIO_PIN_4, AFIO_MODE_4); //AFIO_FUN_PWM
#endif
#if (HTCFG_PWM1_EN == 1)
AFIO_GPxConfig(GPIO_PC, AFIO_PIN_5, AFIO_MODE_4); //AFIO_FUN_PWM
#endif
#if (HTCFG_PWM2_EN == 1)
AFIO_GPxConfig(GPIO_PC, AFIO_PIN_8, AFIO_MODE_4); //AFIO_FUN_PWM
#endif
#if (HTCFG_PWM3_EN == 1)
AFIO_GPxConfig(GPIO_PC, AFIO_PIN_9, AFIO_MODE_4); //AFIO_FUN_PWM
#endif
{
TM_TimeBaseInitTypeDef TimeBaseInit;
TimeBaseInit.Prescaler = 1000 - 1; // Timer clock = CK_AHB / HTCFG_PWM_TM_PRESCALER
TimeBaseInit.CounterReload = 48000000/1/HTCFG_PWM_FREQ_HZ - 1; //设置成50K,再分频1000,为50hz
TimeBaseInit.RepetitionCounter = 0;
TimeBaseInit.CounterMode = TM_CNT_MODE_UP;
TimeBaseInit.PSCReloadTime = TM_PSC_RLD_IMMEDIATE;
TM_TimeBaseInit(HT_GPTM0, &TimeBaseInit);
TM_CRRPreloadCmd(HT_GPTM0, ENABLE);
/* Clear Update Event Interrupt flag since the "TM_TimeBaseInit()" writes the UEV1G bit */
TM_ClearFlag(HT_GPTM0, TM_FLAG_UEV);
}
{ /* Channel n output configuration */
TM_OutputInitTypeDef OutInit;
OutInit.OutputMode = TM_OM_PWM1;
OutInit.Control = TM_CHCTL_ENABLE;
OutInit.ControlN = TM_CHCTL_DISABLE;
OutInit.Polarity = TM_CHP_NONINVERTED;
OutInit.PolarityN = TM_CHP_NONINVERTED;
OutInit.IdleState = MCTM_OIS_LOW;
OutInit.IdleStateN = MCTM_OIS_HIGH;
OutInit.Compare = HTCFG_PWM_IDLE_DUTY;
OutInit.AsymmetricCompare = 0;
#if (HTCFG_PWM0_EN == 1)
OutInit.Channel = TM_CH_0;
TM_OutputInit(HT_GPTM0, &OutInit); // CH0 Start Output as default value
TM_CHCCRPreloadConfig(HT_GPTM0, TM_CH_0, ENABLE);
#endif
#if (HTCFG_PWM1_EN == 1)
OutInit.Channel = TM_CH_1;
TM_OutputInit(HT_GPTM0, &OutInit); // CH1 Start Output as default value
TM_CHCCRPreloadConfig(HT_GPTM0, TM_CH_1, ENABLE);
#endif
#if (HTCFG_PWM2_EN == 1)
OutInit.Channel = TM_CH_2;
TM_OutputInit(HT_GPTM0, &OutInit); // CH2 Start Output as default value
TM_CHCCRPreloadConfig(HT_GPTM0, TM_CH_2, ENABLE);
#endif
#if (HTCFG_PWM3_EN == 1)
OutInit.Channel = TM_CH_3;
TM_OutputInit(HT_GPTM0, &OutInit); // CH3 Start Output as default value
TM_CHCCRPreloadConfig(HT_GPTM0, TM_CH_3, ENABLE);
#endif
}
#if (LIBCFG_MCTM0)
if (HT_GPTM0 == HT_MCTM0)
{
// Only MCTM need OE Enable
MCTM_CHMOECmd(HT_GPTM0, ENABLE);
// Enable MT_CHnN
//MCTM_ChannelNConfig(HTCFG_PWM_TM_PORT, HTCFG_PWM_TM_CH, TM_CHCTL_ENABLE);
}
#endif
/* Enable Update Event interrupt */
NVIC_EnableIRQ(GPTM0_IRQn);
#if 0 // Default enable or disable
TM_Cmd(HTCFG_PWM_TM_PORT, ENABLE);
#endif
}
- 等等其他外设各种demo都有
- 还有一些移植的算法例如中值滤波等等就不一一展示
u16 median_filtering() //中值滤波算法实现
{
int senseV[median_filtering_length];
int i;
int j;
int k;
for( i = 0; i < median_filtering_length; i++){
senseV[i] = firstWater;
delay_ms(3);
}
for( j = 0; j < median_filtering_length; j++ ){
for( k = j; k <median_filtering_length; k++ ){
if(senseV[j] > senseV[k]){
int tmp = senseV[j];
senseV[j] = senseV[k];
senseV[k] = tmp;
}
}
}
return senseV[median_filtering_length/2];
}
四、HT32认识与开源项目可移植性说明
4.1 HT32F52352/64pin-LQFP,以下两图非常重要,封装引脚图过长,后续有整理。这几张图都得设为屏保,做项目一定会用得到,经常用。
该系列单片机的系统结构包括 Arm® Cortex®-M0+ 处理器、总线结构和存储器体系,Cortex®-M0+ 处理器是新一代的处理器内核,提供了许多新的特性。集成和先进的特性使得 Cortex®-M0+ 处理器适合于需要高性能和低功耗单片机的市场产品。简而言之,Cortex®-M0+ 处理器包含 AHB-Lite 总线接口。根据不同的目的和目标存储空间,Cortex®-M0+ 处理器访问所有存储器都是在这条总线上执行的。存储器体系采用了哈佛结构,
预先定义的存储器映射和高达 4GB 的存储空间,使系统灵活和可扩展。
4.2 可移植性
该单片机的效用还是很高的,我在学习这款单片机的时候移植过STM32各种有趣的项目,例如经典的平衡小车,蓝牙小车,TF读卡器外置音乐盒等等。和STM32同为32位,有基础的朋友可以很快上手,没有基础的朋友可以根据我的总结的demo也可以很快上手,demo十分丰富,基本涵盖竞赛所需所有的外设或者传感器应用。希望可以帮助大家。下图可展示部分整理资料。