1、建立开发调试环境
pack支持包下载:https://www.mindmotion.com.cn/support/software/keil_pack/
安装keil MDK软件,进行和谐。
安装pack包中的MindMotion.MM32F0120_DFP.0.9.3.pack
即开发环境搭建完成。
打开一个工程进行编译 :
2、调试串口打印,输出Hello 21ic, HelloMM32F0121
打开一个官方的例程,在platform.c文件中,已经定义了fputc函数,将串口2与printf进行绑定。直接 printf可在串口输出
printf("Hello 21ic, HelloMM32F0121 ");
3、呼吸灯实验
原理图中,两个LED连接的是PB14、PB15;这两个引脚,可用的定时 器是TIM1;
电路原理图:
数据手册中,这两个引脚的复用。
打开一个PWM工程,修改输出的引脚
动态修改TIM_SetCompare3 函数来改变 占空比
效果:
4、RTC实时时钟外设,打印RTC的时间戳
/***********************************************************************************************************************
[url=home.php?mod=space&uid=288409]@file[/url] rtc_calendar.c
[url=home.php?mod=space&uid=187600]@author[/url] FD Team
[url=home.php?mod=space&uid=212281]@date[/url] 12-Dec-2023
[url=home.php?mod=space&uid=247401]@brief[/url] THIS FILE PROVIDES ALL THE SYSTEM FUNCTIONS.
**********************************************************************************************************************
@attention
<h2><center>© Copyright(c) <2023> <MindMotion></center></h2>
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*********************************************************************************************************************/
/* Define to prevent recursive inclusion */
#define _RTC_CALENDAR_C_
/* Files include */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "platform.h"
#include "rtc_calendar.h"
/**
* @addtogroup MM32F0120_LibSamples
* @{
*/
/**
* @addtogroup RTC
* @{
*/
/**
* @addtogroup RTC_Calendar
* @{
*/
/* Private typedef ****************************************************************************************************/
/* Private define *****************************************************************************************************/
/* Private macro ******************************************************************************************************/
/* Private variables **************************************************************************************************/
const uint8_t RTC_DayOfMonth[12] =
{
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
RTC_CalendarTypeDef RTC_Calendar;
/* Private functions **************************************************************************************************/
/***********************************************************************************************************************
* @brief
* [url=home.php?mod=space&uid=536309]@NOTE[/url] none
* @param none
* @retval none
*********************************************************************************************************************/
uint8_t RTC_LeapYear(uint16_t Year)
{
if (
(((Year % 400) == 0)) || /* Century Leap Year */
(((Year % 100) != 0) && ((Year % 4) == 0)) /* Normal Leay Year */
)
{
return (1);
}
else
{
return (0);
}
}
/***********************************************************************************************************************
* @brief
* @note none
* @param none
* @retval none
*********************************************************************************************************************/
uint8_t RTC_GetWeek(uint16_t Year, uint8_t Month, uint8_t Day)
{
int w, c, y;
/* Month 1 Or 2 of This Year Must Be As Last Month 13 Or 14 */
if ((Month == 1) || (Month == 2))
{
Month += 12;
Year -= 1;
}
w = 0; /* Weekday */
c = Year / 100; /* Century */
y = Year % 100; /* Year */
w = y + (y / 4) + (c / 4) - (2 * c) + (26 * (Month + 1) / 10) + Day - 1;
while (w < 0)
{
w += 7;
}
w %= 7;
return (w);
}
/***********************************************************************************************************************
* @brief
* @note none
* @param none
* @retval none
*********************************************************************************************************************/
void RTC_UpdateCalendar(void)
{
static uint32_t PreTotalDay = 0;
uint32_t TotalSecond = 0;
uint32_t TotalDay = 0;
uint16_t Year = 1970;
uint8_t Month = 0;
TotalSecond = RTC_GetCounter();
TotalDay = TotalSecond / 86400;
if (PreTotalDay != TotalDay)
{
PreTotalDay = TotalDay;
while (TotalDay >= 365)
{
if (RTC_LeapYear(Year) == 1)
{
if (TotalDay >= 366)
{
TotalDay -= 366;
}
else
{
break;
}
}
else
{
TotalDay -= 365;
}
Year++;
}
RTC_Calendar.year = Year;
while (TotalDay >= 28)
{
if ((Month == 1) && (RTC_LeapYear(RTC_Calendar.year) == 1))
{
if (TotalDay >= 29)
{
TotalDay -= 29;
}
else
{
break;
}
}
else
{
if (TotalDay >= RTC_DayOfMonth[Month])
{
TotalDay -= RTC_DayOfMonth[Month];
}
else
{
break;
}
}
Month++;
}
RTC_Calendar.month = Month + 1;
RTC_Calendar.day = TotalDay + 1;
RTC_Calendar.week = RTC_GetWeek(RTC_Calendar.year, RTC_Calendar.month, RTC_Calendar.day);
}
RTC_Calendar.hour = (TotalSecond % 86400) / 3600;
RTC_Calendar.minute = ((TotalSecond % 86400) % 3600) / 60;
RTC_Calendar.second = ((TotalSecond % 86400) % 3600) % 60;
}
/***********************************************************************************************************************
* @brief
* @note none
* @param none
* @retval none
*********************************************************************************************************************/
void RTC_SetDateTime(uint16_t Year, uint8_t Month, uint8_t Day, uint8_t Hour, uint8_t Minute, uint8_t Second)
{
uint32_t TotalSecond = 0;
uint16_t y = 0;
uint8_t m = 0;
if ((Year >= 1970) && (Year <= 2099))
{
for (y = 1970; y < Year; y++)
{
if (RTC_LeapYear(y) == 1)
{
TotalSecond += 31622400; /* Total Seconds Of Leap Year */
}
else
{
TotalSecond += 31536000; /* Total Seconds Of Normal Year */
}
}
for (m = 0; m < (Month - 1); m++)
{
TotalSecond += RTC_DayOfMonth[m] * 86400; /* Total Seconds Of Month */
if ((RTC_LeapYear(Year) == 1) && (m == 1))
{
TotalSecond += 86400;
}
}
TotalSecond += (uint32_t)(Day - 1) * 86400; /* Total Seconds Of Day */
TotalSecond += (uint32_t)Hour * 3600; /* Total Seconds Of Hour */
TotalSecond += (uint32_t)Minute * 60; /* Total Seconds Of Minute */
TotalSecond += Second;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_RTC | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
RTC_SetCounter(TotalSecond);
RTC_WaitForLastTask();
RTC_UpdateCalendar();
}
else
{
printf("\r\nError Date & Time!!!\r\n");
}
}
/***********************************************************************************************************************
* @brief
* @note none
* @param none
* @retval none
*********************************************************************************************************************/
void RTC_PrintDateTime(void)
{
printf("\r\n%04d-%02d-%02d", RTC_Calendar.year, RTC_Calendar.month, RTC_Calendar.day);
switch (RTC_Calendar.week)
{
case 0:
printf(" SUN ");
break;
case 1:
printf(" MON ");
break;
case 2:
printf(" TUE ");
break;
case 3:
printf(" WED ");
break;
case 4:
printf(" THU ");
break;
case 5:
printf(" FRI ");
break;
case 6:
printf(" SAT ");
break;
default:
break;
}
printf("---%02d:%02d:%02d\r\n", RTC_Calendar.hour, RTC_Calendar.minute, RTC_Calendar.second);
}
/***********************************************************************************************************************
* @brief
* @note none
* @param none
* @retval none
*********************************************************************************************************************/
void RTC_LoadDefault(void)
{
char Date[20], Time[20];
char Text[6][5];
uint8_t i = 0, Index = 0, Month = 0;
char *MonthTable[12] =
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
};
char *str;
memset(Date, 0, sizeof(Date));
memset(Time, 0, sizeof(Time));
memset(Text, 0, sizeof(Text));
memcpy(Date, __DATE__, sizeof(__DATE__));
memcpy(Time, __TIME__, sizeof(__TIME__));
str = strtok(Date, " ");
while (str != NULL)
{
memcpy(Text[Index++], str, strlen(str));
str = strtok(NULL, " ");
}
str = strtok(Time, ":");
while (str != NULL)
{
memcpy(Text[Index++], str, strlen(str));
str = strtok(NULL, ":");
}
for (i = 0; i < 12; i++)
{
if (0 == strcmp(Text[0], MonthTable[i]))
{
Month = i + 1;
}
}
RTC_Calendar.day = atoi(Text[1]);
RTC_Calendar.month = Month;
RTC_Calendar.year = atoi(Text[2]);
RTC_Calendar.hour = atoi(Text[3]);
RTC_Calendar.minute = atoi(Text[4]);
RTC_Calendar.second = atoi(Text[5]);
RTC_SetDateTime(RTC_Calendar.year, RTC_Calendar.month, RTC_Calendar.day, RTC_Calendar.hour, RTC_Calendar.minute, RTC_Calendar.second);
}
/***********************************************************************************************************************
* @brief
* @note none
* @param none
* @retval none
*********************************************************************************************************************/
void RTC_Configure(void)
{
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_RTC | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
BKP_DeInit();
if (BKP_ReadBackupRegister(BKP_DR1) != 0x5B5B)
{
RCC_LSEConfig(RCC_LSE_ON);
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{
}
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForSynchro();
RTC_WaitForLastTask();
RTC_ITConfig(RTC_IT_SEC, ENABLE);
RTC_WaitForLastTask();
RTC_SetPrescaler(32767);
RTC_WaitForLastTask();
printf("\r\n%s", __FUNCTION__);
BKP_WriteBackupRegister(BKP_DR1, 0x5B5B);
}
else
{
printf("\r\nNeed't to configure RTC.");
RTC_WaitForSynchro();
RTC_ITConfig(RTC_IT_SEC, ENABLE);
RTC_WaitForLastTask();
}
NVIC_InitStruct.NVIC_IRQChannel = RTC_BKP_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
RTC_LoadDefault();
}
/***********************************************************************************************************************
* @brief
* @note none
* @param none
* @retval none
*********************************************************************************************************************/
void RTC_Calendar_Sample(void)
{
printf("\r\nTest %s", __FUNCTION__);
RTC_Configure();
while (1)
{
RTC_PrintDateTime();
PLATFORM_LED_Toggle(LED1);
PLATFORM_DelayMS(1000);
}
}
运行效果
5、I2C主模式实验,写入“Hello 21ic, Hello MM32F0121"字符串并打印对应读取的数据内容
电路原理图中,IIC连接的是一个at3224的EEPROM芯片
代码 :
/***********************************************************************************************************************
@file i2c_master_eeprom_polling.c
@author FD Team
@date 12-Dec-2023
@brief THIS FILE PROVIDES ALL THE SYSTEM FUNCTIONS.
**********************************************************************************************************************
@attention
<h2><center>© Copyright(c) <2023> <MindMotion></center></h2>
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*********************************************************************************************************************/
/* Define to prevent recursive inclusion */
#define _I2C_MASTER_EEPROM_POLLING_C_
/* Files include */
#include <stdio.h>
#include "platform.h"
#include "i2c_master_eeprom_polling.h"
/**
* @addtogroup MM32F0120_LibSamples
* @{
*/
/**
* @addtogroup I2C
* @{
*/
/**
* @addtogroup I2C_Master_EEPROM_Polling
* @{
*/
/* Private typedef ****************************************************************************************************/
/* Private define *****************************************************************************************************/
/* Private macro ******************************************************************************************************/
#define EEPROM_I2C_ADDRESS 0xA0
#define EEPROM_PAGE_SIZE 0x08
/* Private variables **************************************************************************************************/
/* Private functions **************************************************************************************************/
/***********************************************************************************************************************
* @brief
* @note none
* @param none
* @retval none
*********************************************************************************************************************/
void I2C_Configure(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
I2C_InitTypeDef I2C_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
I2C_DeInit(I2C1);
I2C_StructInit(&I2C_InitStruct);
I2C_InitStruct.I2C_Mode = I2C_MODE_MASTER;
I2C_InitStruct.I2C_OwnAddress = I2C_OWN_ADDRESS;
I2C_InitStruct.I2C_ClockSpeed = 100000;
I2C_Init(I2C1, &I2C_InitStruct);
I2C_TargetAddressConfig(I2C1, EEPROM_I2C_ADDRESS);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_1);
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStruct);
I2C_Cmd(I2C1, ENABLE);
}
/***********************************************************************************************************************
* @brief
* @note none
* @param none
* @retval none
*********************************************************************************************************************/
void I2C_TxData_Polling(uint8_t *Buffer, uint8_t Length)
{
uint8_t i = 0;
for (i = 0; i < Length; i++)
{
I2C_SendData(I2C1, Buffer[i]);
while (RESET == I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE))
{
}
}
}
/***********************************************************************************************************************
* @brief
* @note none
* @param none
* @retval none
*********************************************************************************************************************/
void I2C_RxData_Polling(uint8_t *Buffer, uint16_t Length)
{
uint8_t i = 0;
for (i = 0; i < Length; i++)
{
I2C_ReadCmd(I2C1);
while (RESET == I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_RFNE))
{
}
Buffer[i] = I2C_ReceiveData(I2C1);
}
}
/***********************************************************************************************************************
* @brief
* @note none
* @param none
* @retval none
*********************************************************************************************************************/
void EEPROM_WritePage(uint8_t Address, uint8_t *Buffer, uint8_t Length)
{
I2C_TxData_Polling((uint8_t *)&Address, 0x01);
I2C_TxData_Polling((uint8_t *)Buffer, Length);
while (RESET == I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE))
{
}
I2C_GenerateSTOP(I2C1);
while (RESET == I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE))
{
}
}
/***********************************************************************************************************************
* @brief
* @note none
* @param none
* @retval none
*********************************************************************************************************************/
void EEPROM_ReadData(uint8_t Address, uint8_t *Buffer, uint8_t Length)
{
I2C_TxData_Polling((uint8_t *)&Address, 0x01);
I2C_RxData_Polling((uint8_t *)Buffer, Length);
I2C_GenerateSTOP(I2C1);
while (RESET == I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE))
{
}
}
/***********************************************************************************************************************
* @brief
* @note none
* @param none
* @retval none
*********************************************************************************************************************/
void EEPROM_WriteData(uint8_t Address, uint8_t *Buffer, uint8_t Length)
{
uint8_t Start = 0;
uint8_t StartCount = 0, PageNumber = 0, FinalCount = 0;
if ((Address % EEPROM_PAGE_SIZE) == 0)
{
StartCount = 0;
PageNumber = Length / EEPROM_PAGE_SIZE;
FinalCount = Length % EEPROM_PAGE_SIZE;
}
else
{
Start = Address % EEPROM_PAGE_SIZE;
if (((Start + Length) / EEPROM_PAGE_SIZE) == 0)
{
StartCount = Length;
PageNumber = 0;
FinalCount = 0;
}
else
{
StartCount = EEPROM_PAGE_SIZE - Start;
PageNumber = (Length - StartCount) / EEPROM_PAGE_SIZE;
FinalCount = (Length - StartCount) % EEPROM_PAGE_SIZE;
}
}
if (StartCount)
{
EEPROM_WritePage(Address, Buffer, StartCount);
Address += StartCount;
Buffer += StartCount;
PLATFORM_DelayMS(50);
}
while (PageNumber--)
{
EEPROM_WritePage(Address, Buffer, EEPROM_PAGE_SIZE);
Address += EEPROM_PAGE_SIZE;
Buffer += EEPROM_PAGE_SIZE;
PLATFORM_DelayMS(50);
}
if (FinalCount)
{
EEPROM_WritePage(Address, Buffer, FinalCount);
}
}
/***********************************************************************************************************************
* @brief
* @note none
* @param none
* @retval none
*********************************************************************************************************************/
void I2C_Master_EEPROM_Polling_Sample(void)
{
uint8_t i = 0;
uint8_t ReadBuffer[50];
uint8_t WriteBuffer[]="Hello 21ic, Hello MM32F0121";
printf("\r\nTest %s", __FUNCTION__);
I2C_Configure();
/*for (i = 0; i < 20; i++)
{
ReadBuffer[i] = 0;
WriteBuffer[i] = i + 0x30;
}*/
printf("\r\n\r\nEEPROM Write : ");
EEPROM_WriteData(0, WriteBuffer, sizeof(WriteBuffer));
printf("OK");
printf("\r\n\r\nEEPROM Read : \r\n");
EEPROM_ReadData(0, ReadBuffer, sizeof(WriteBuffer));
for (i = 0; i < 20; i++)
{
printf("%c ", ReadBuffer[i]);
if (0 == ((i + 1) % 10))
{
printf("\r\n");
}
}
while (1)
{
PLATFORM_LED_Toggle(LED1);
PLATFORM_DelayMS(100);
}
}
运行效果:
6、SPI主模式实验,打印写入“Hello 21ic, Hello MM32F0121"
开发板上有一片SPI Flash
void SPI_Master_FLASH_Polling_Sample(void)
{
uint8_t i = 0;
uint8_t ReadBuffer[100];
uint8_t WriteBuffer[]="Hello 21ic, Hello MM32F0121";
printf("\r\nTest %s", __FUNCTION__);
SPI_Configure();
SPI_FLASH_ReadDeviceID();
SPI_FLASH_ReadJEDEC_ID();
printf("\r\nSPI FLASH Sector Erase...");
SPI_FLASH_SectorErase(0);
printf("\r\nSPI FLASH Read...");
SPI_FLASH_FastRead(0, ReadBuffer, 100);
for (i = 0; i < 100; i++)
{
if (0 == (i % 10))
{
printf("\r\n");
}
printf("0x%02x ", ReadBuffer[i]);
}
printf("\r\nSPI FLASH Page Program...");
SPI_FLASH_PageProgram(0, WriteBuffer, sizeof(WriteBuffer));
printf("\r\nSPI FLASH Read...");
SPI_FLASH_FastRead(0, ReadBuffer, sizeof(WriteBuffer));
for (i = 0; i < sizeof(WriteBuffer); i++)
{
if (0 == (i % 10))
{
printf("\r\n");
}
printf("%c ", ReadBuffer[i]);
}
while (1)
{
PLATFORM_LED_Toggle(LED1);
PLATFORM_DelayMS(100);
}
}
7、ADC采样实验
原理图中ADC引脚为PA3,连接到一个电位器。
这里使用ADC_AnyChannel_ContinuousScan_Polling_Sample例程;
运行后,串口输出结果为ADC转换值计算的电压值。
|
|